         (when (not (= identity f))
           false)))))
 
+(defn throttle [ms f]
+  (let [timer (atom nil)]
+    (fn [e]
+      (.persist e)
+      (js/clearTimeout @timer)
+      (reset! timer (js/setTimeout #(f e) ms)))))
+
 (defn quick-search [{:keys [highlighted-index loading? ac-results] :as app} owner]
   (reify
-    om/IWillMount
-    (will-mount [_]
-      (let [text-chan (or (om/get-state owner :text-chan) (chan))
-            internal-text-chan (chan)
-            throttled (throttle internal-text-chan 250)]
-        (pipe throttled text-chan)
-        (om/set-state! owner :internal-text-chan internal-text-chan)))
     om/IRenderState
-    (render-state [this {:keys [internal-text-chan text]}]
+    (render-state [this {:keys [text-chan text]}]
       (dom/form {:class "search" :autoComplete "off"
                  ;; the search widget should prob not need to know about
                  ;; autocomplete results (or act on them)

                    :name "query"
                    :autoComplete "off"
                    :autoFocus "autofocus"
                    :on-input #(put-text % internal-text-chan owner)
                    :on-key-down #(maybe-nav % app ac-results)})
        (dom/ul {:class "ac-results"}
          (map-indexed

  (navigate-to (:href ac-result))
  false)

(defn maybe-nav [e app ac-results]
  (when app
    (let [ctrl? (.-ctrlKey e)
