                :id "output-area"
                :dangerouslySetInnerHTML #js {:__html (marked input)}})))))
 
-;; The main app
+;; State transformations
 
 (defn update-many!
-  "Sequentially updates multiple keys on Om cursor to the given value."
+  "Updates multiple keys on Om cursor to the given value."
   [app ks v]
   (doseq [k ks]
     (om/update! app k v)))

                  (dom/span #js {:className "delete-button"
                                 :onClick (fn [e] (delete-click % app))} "x")
                  (dom/span #js {:className "left-menu-title"
                                 :onClick (fn [e] (update-current e app))}
                    (om/value %)))
               (:titles app)))))))

;; Save button

(defn save-button-click
  "Sends a :save command on the app channel."
  [app]
  (put! (:channel @app) [:save nil]))

(defn saved?
  "Determines whether or not the app state has changed since last
   save."
  [{:keys [input last-input title last-title]}]
  (and
    (= input last-input)
    (= title last-title)))

(defn save-button
  "Component that renders the save button. The button is disabled
   when there are no changes to title or input. Clicking the save
   button triggers the app state to update and saves to localStorage."
  [app owner]
  (reify
    om/IRender
    (render [_]
      (dom/button #js {:id "save-button"
                       :disabled (saved? app)
                       :className (when (saved? app) "disabled")
                       :onClick #(save-button-click app)}
                  (if (saved? app)
                    "saved"
                    "save")))))

;; Editor



(enable-console-print!)

;; Implements ICloneable on string and js/string so that
;; React can handle these properly.

(extend-type string
  ICloneable
  (-clone [s] (js/String. s)))
