|  | @@ -27,14 +27,14 @@
 | 
	
		
			
				|  |  |  (defn highest [dir data] (apply max (map dir data)))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ; COLUMN NAMES
 | 
	
		
			
				|  |  | -(defn upgrade-letter-code [s]
 | 
	
		
			
				|  |  | +(defn increment-letter-code [s]
 | 
	
		
			
				|  |  |    (let [l (last s)]
 | 
	
		
			
				|  |  |      (cond
 | 
	
		
			
				|  |  |        (empty? s) [65]
 | 
	
		
			
				|  |  | -      (= l 90) (conj (upgrade-letter-code (subvec s 0 (dec (count s)))) 65)
 | 
	
		
			
				|  |  | +      (= l 90) (conj (increment-letter-code (subvec s 0 (dec (count s)))) 65)
 | 
	
		
			
				|  |  |        :else (conj (subvec s 0 (dec (count s))) (inc l)))))
 | 
	
		
			
				|  |  |  (defn next-letter [lc]
 | 
	
		
			
				|  |  | -  (apply str (map char (upgrade-letter-code (mapv #(.charCodeAt % 0) lc)))))
 | 
	
		
			
				|  |  | +  (apply str (map char (increment-letter-code (mapv #(.charCodeAt % 0) lc)))))
 | 
	
		
			
				|  |  |  (def col-letters (iterate next-letter "A"))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -54,7 +54,10 @@
 | 
	
		
			
				|  |  |  (def parse-variables (memoize (fn [expression]
 | 
	
		
			
				|  |  |                                  (js->clj (.getVariables mathjs expression)))))
 | 
	
		
			
				|  |  |  (def evaluate-expression (memoize (fn [expression variables]
 | 
	
		
			
				|  |  | -                                    (.evaluate mathjs expression (clj->js variables)))))
 | 
	
		
			
				|  |  | +                                    (let [answer (.evaluate mathjs expression (clj->js variables))]
 | 
	
		
			
				|  |  | +                                      (if (nil? (.-error answer))
 | 
	
		
			
				|  |  | +                                        answer
 | 
	
		
			
				|  |  | +                                        :calc-error)))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (def str->rc (memoize (fn [s]
 | 
	
		
			
				|  |  |                          (let [c (re-find #"^[A-Z]+" s)
 | 
	
	
		
			
				|  | @@ -129,6 +132,8 @@
 | 
	
		
			
				|  |  |  (defn on-enter-cell [c r e]
 | 
	
		
			
				|  |  |    (println (str "entering cell " c r))
 | 
	
		
			
				|  |  |    (swap! data-atom #(toggle-display % c r :value)))
 | 
	
		
			
				|  |  | +(defn on-change [c r datum e]
 | 
	
		
			
				|  |  | +  (update-value c r datum (.. e -target -value)))
 | 
	
		
			
				|  |  |  (defn on-leave-cell [c r e]
 | 
	
		
			
				|  |  |    (println (str "leaving cell " c r))
 | 
	
		
			
				|  |  |    (swap! data-atom #(as-> % data
 | 
	
	
		
			
				|  | @@ -145,7 +150,7 @@
 | 
	
		
			
				|  |  |      ^{:key (str c r)} [:td [:input {:value (if (= (get datum :view nil) :value)
 | 
	
		
			
				|  |  |                                               (get datum :value "")
 | 
	
		
			
				|  |  |                                               (get datum :error (get datum :display (get datum :value ""))))
 | 
	
		
			
				|  |  | -                                    :on-change #(update-value c r datum (.. % -target -value))
 | 
	
		
			
				|  |  | +                                    :on-change (partial on-change c r datum)
 | 
	
		
			
				|  |  |                                      :on-blur (partial on-leave-cell c r)
 | 
	
		
			
				|  |  |                                      :on-focus (partial on-enter-cell c r)}]]))
 | 
	
		
			
				|  |  |  (defn row [r cols data]
 |