-
-
Save IwanKaramazow/ac22bf8653ce9274292c6bf993d9cc9f to your computer and use it in GitHub Desktop.
Autocomplete tutorial augmented w/ a colossal join
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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