Skip to content

Instantly share code, notes, and snippets.

@IwanKaramazow
Created April 4, 2016 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IwanKaramazow/ac22bf8653ce9274292c6bf993d9cc9f to your computer and use it in GitHub Desktop.
Save IwanKaramazow/ac22bf8653ce9274292c6bf993d9cc9f to your computer and use it in GitHub Desktop.
Autocomplete tutorial augmented w/ a colossal join
(def base-url
"http://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=")
(defn jsonp
([uri] (jsonp (chan) uri))
([c uri]
(let [gjsonp (Jsonp. (Uri. uri))]
(.send gjsonp nil #(put! c %))
c)))
(defmulti read om/dispatch)
(defmethod read :search/results
[{:keys [state ast] :as env} k {:keys [query]}]
(merge
{:value (get @state k [])}
(when-not (or (string/blank? query)
(< (count query) 3))
{:search ast})))
(defmethod read :root-query
[{:keys [parser query ast target] :as env} key _]
(let [search (parser env query target)]
(if (and target (not-empty search))
{:search (update-in ast [:query] (fn [query] search))}
{:value (parser env query)})))
(defn send-to-chan [c]
(fn [{:keys [search] :as env} cb]
(when search
(let [{[search] :children} (om/query->ast (get-in (first search) [:root-query]))
query (get-in search [:params :query])]
(put! c [query cb])))))
(defn search-loop [c]
(go
(loop [[query cb ] (<! c)]
(let [[_ results] (<! (jsonp (str base-url query)))]
(cb {:search/results results} ))
(recur (<! c)))))
(defn result-list [results]
(dom/ul #js {:key "result-list"}
(map-indexed #(dom/li #js {:key %} %2) results)))
(defn search-field [ac query]
(dom/input
#js {:key "search-field"
:value query
:onChange
(fn [e]
(om/set-query! ac
{:params {:query (.. e -target -value)}}))}))
(defui AutoCompleter
static om/IQueryParams
(params [_]
{:query ""})
static om/IQuery
(query [_]
'[(:search/results {:query ?query})])
Object
(render [this]
(let [{:keys [search/results]} (om/props this)]
(dom/div nil
(dom/h2 nil "Autocompleter")
(cond->
[(search-field this (:query (om/get-params this)))]
(not (empty? results)) (conj (result-list results)))))))
(def auto-completer (om/factory AutoCompleter))
(defui Root
static om/IQuery
(query [_]
[{:root-query (om/get-query AutoCompleter)}])
Object
(render [this]
(let [{:keys [root-query]} (om/props this)]
(dom/div nil
(auto-completer root-query)))))
(def send-chan (chan))
(def reconciler
(om/reconciler
{:state {:search/results []}
:parser (om/parser {:read read})
:send (send-to-chan send-chan)
:remotes [:remote :search]}))
(search-loop send-chan)
(om/add-root! reconciler Root
(gdom/getElement "app"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment