                  new-deck (if (:_id deck) deck (assoc deck :_id new-id))]
              (om/update! cursor :decks (conj decks new-deck))
              (om/set-state! owner :deck new-deck)))))))
-
-(defn match [identity query]
-  (if (empty? query)
-    []
-    (let [cards (->> (:cards @app-state)
-                     (filter #(and (allowed? % identity)
-                                   (not= "Special" (:setname %))
-                                   (alt-art? %)))
-                     (distinct-by :title))]
-      (take 10 (filter #(not= (.indexOf (.toLowerCase (:title %)) (.toLowerCase query)) -1) cards)))))
-
-(defn handle-edit [owner]
-  (let [text (.-value (om/get-node owner "deck-edit"))]
-    (om/set-state! owner :deck-edit text)
-    (om/set-state! owner [:deck :cards] (parse-deck (om/get-state owner [:deck :identity :side]) text))))
-
-(defn handle-delete [cursor owner]
-  (authenticated
-   (fn [user]
-     (let [deck (om/get-state owner :deck)]
-       (try (js/ga "send" "event" "deckbuilder" "delete") (catch js/Error e))
-       (go (let [response (<! (POST "/data/decks/delete" deck :json))]))
-       (om/transact! cursor :decks (fn [ds] (remove #(= deck %) ds)))
-       (om/set-state! owner :deck (first (sort-by :date > (:decks @cursor))))))))
 
 (defn html-escape [st]
   (escape st {\< "&lt;" \> "&gt;" \& "&amp;" \" "#034;"}))

             "</section></deck>")
        blob (js/Blob. (clj->js [xml]) #js {:type "application/download"})]
    (.createObjectURL js/URL blob)))

(defn handle-keydown [owner event]
  (let [selected (om/get-state owner :selected)

  (go (<! (timeout 500))
      (-> owner (om/get-node "deckname") js/$ .select)))

(defn end-edit [owner]
  (om/set-state! owner :edit false)
  (om/set-state! owner :query "")
  (-> owner (om/get-node "viewport") js/$ (.removeClass "edit")))

(defn handle-edit [owner]
  (let [text (.-value (om/get-node owner "deck-edit"))]
    (om/set-state! owner :deck-edit text)
    (om/set-state! owner
                   [:deck :cards]
                   (parse-deck (om/get-state owner [:deck :identity :side])
                               text))))

(defn delete-deck [owner]
  (om/set-state! owner :delete true)
  (deck->str owner)
  (-> owner (om/get-node "viewport") js/$ (.addClass "delete"))
  (try (js/ga "send" "event" "deckbuilder" "delete") (catch js/Error e)))

(defn end-delete [owner]
  (om/set-state! owner :delete false)
  (-> owner (om/get-node "viewport") js/$ (.removeClass "delete")))

(defn handle-delete [cursor owner]
  (authenticated
   (fn [user]
     (let [deck (om/get-state owner :deck)]
       (try (js/ga "send" "event" "deckbuilder" "delete") (catch js/Error e))
       (go (let [response (<! (POST "/data/decks/delete" deck :json))]))
       (do
         (om/transact! cursor :decks (fn [ds] (remove #(= deck %) ds)))
         (om/set-state! owner :deck (first (sort-by :date > (:decks @cursor))))
         (end-delete owner))))))

(defn new-deck [side owner]
  (om/set-state! owner :deck {:name "New deck" :cards [] :identity (-> side side-identities first)})
  (try (js/ga "send" "event" "deckbuilder" "new" side) (catch js/Error e))
  (edit-deck owner))

(defn save-deck [cursor owner]
  (authenticated
