Skip to content

Instantly share code, notes, and snippets.

@werenall
Last active June 24, 2019 16:10
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 werenall/91da2dceab95a811a52aa67bad108416 to your computer and use it in GitHub Desktop.
Save werenall/91da2dceab95a811a52aa67bad108416 to your computer and use it in GitHub Desktop.
Tooltips managed by re-frame's appdb
(ns myapp.client
(:require [myapp.client.todo :as todo]))
(defn app []
[:div.app-container
{:on-click #(tooltip/destroy-on-click-out (.. % -target))}
[main]])
(defn hello-tooltip [id]
[:div.tooltip.tooltip--bottom
[:button {:on-click #(rf/dispatch [::tooltip/destroy-by-id id])} "x"]
[:p "Hello there!"]])
(defn main []
(let [tooltip-id "my-first-tooltip"
tooltip-data (rf/subscribe [::tooltip/by-id tooltip-id])]
(fn []
[:div.tooltip-controller
{:class (tooltip/gen-controller-class tooltip-id)}
[:button
{:on-click #(if @tooltip-data
(rf/dispatch [::tooltip/destroy-by-id tooltip-id])
(rf/dispatch [::tooltip/register {:id tooltip-id}]))}
"spawn tooltip 1"]
(when @tooltip-data
[hello-tooltip tooltip-id])])))
(ns myapp.tooltip
(:require [re-frame.core :as rf]
[clojure.string :as str]))
(def ^:const controller-class-prefix "js-tooltip-controller-")
(def ^:const controller-class-pattern
(re-pattern (str controller-class-prefix "([\\w\\-]+)")))
(rf/reg-sub
::controls
(fn [db _]
(:tooltip-controls db)))
(rf/reg-sub
::by-id
(fn [db _]
(rf/subscribe [::controls]))
(fn [tooltips-controls [_ id]]
(get tooltips-controls id)))
(defn default-tooltip-data []
{:id (str (random-uuid))
:destroy-on-click-out? true})
(rf/reg-event-db
::register
(fn [db [_ data]]
(let [data (merge (default-tooltip-data) data)]
(assoc-in db [:tooltip-controls (:id data)] data))))
(rf/reg-event-db
::destroy-by-id
(fn [db [_ id]]
(update db :tooltip-controls dissoc id)))
(rf/reg-event-db
::destroy-by-ids
(fn [db [_ ids]]
(update db :tooltip-controls
#(apply dissoc % ids))))
(defn find-tooltip-controller-class-in-node [node]
(some->> (.-className node)
(re-find controller-class-pattern)
(first)))
(defn find-tooltip-controller-class [node]
(or (find-tooltip-controller-class-in-node node)
(some-> (.-parentNode node) (find-tooltip-controller-class))))
(defn destroy-on-click-out [clicked-node]
(let [clicked-controller (some->
(find-tooltip-controller-class clicked-node)
(str/split controller-class-prefix)
(second))
controls-ids (->> @(rf/subscribe [::controls])
(vals)
(filter :destroy-on-click-out?)
(map :id)
(set))]
(rf/dispatch [::destroy-by-ids (disj controls-ids clicked-controller)])))
(defn gen-controller-class [tooltip-id]
{:pre (string? tooltip-id)}
(str controller-class-prefix tooltip-id))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment