Skip to content

Instantly share code, notes, and snippets.

@kirked
Last active July 2, 2023 21:31
Show Gist options
  • Save kirked/7aefc94d1a45435a038728d26fd9b373 to your computer and use it in GitHub Desktop.
Save kirked/7aefc94d1a45435a038728d26fd9b373 to your computer and use it in GitHub Desktop.
HTML element class manipulations in Clojurescript (no jQuery)
(defn classes-of
"Get the classes of an element as a Clojure keyword vector."
[e]
(let [words (-> e (.getAttribute "class") (string/split " "))]
(mapv keyword words)))
(defn classes->str
"Change a Clojure keyword seq into an HTML class string."
[classes]
(->> classes (mapv name) (string/join " ")))
(defn class-reset!
"Unconditionally set the classes of an element."
[e classes]
(.setAttribute e "class" (classes->str classes))
e)
(defn class-swap!
"Update the classes of an element using a fn."
[e f]
(class-reset! e (f (classes-of e))))
(defn add-class!
"Add a class to an element."
[e class]
(class-swap! e #(distinct (conj % (keyword class)))))
(defn remove-class!
"Remove a class from an element."
[e class]
(class-swap! e (fn [current] (remove #(= % (keyword class)) current))))
(defn toggle-class!
"Toggle between 2 classes, one of which is already on the element."
[e class1 class2]
(let [toggle-map {(keyword class1) (keyword class2), (keyword class2) (keyword class1)}]
(class-swap! e #(replace toggle-map %))))
@vinurs
Copy link

vinurs commented Jun 20, 2019

great, helps a lot

@robert-pierce
Copy link

remove-class! contains an error. The fn passed to class-swap! should be (fn [current] (remove #(= % (keyword class)) current))). It was missing the %

@kirked
Copy link
Author

kirked commented Jan 24, 2020

Thanks @robert-pierce, fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment