        (style el v)
        (.setAttribute el (name k) v))))
 
-(defn text [el v]
-  (gdom/setTextContent el v))
+(defn text
+  "Get or set element text."
+  ([el]
+     (gdom/getTextContent (select el)))
+  ([el v]
+     (gdom/setTextContent (select el) v)))
 
 (defn classed!
-  "Adds or removes `class` to `el` based on boolean `classed?`."
+  "Add or remove `class` to `el` based on boolean `classed?`."
   [el class classed?]
   (gclasses/enable (select el) class classed?))
 

   (dom-element? node) :dom      ;;It's an actual DOM node
   ))

(defmulti select node-type)
(defmethod select :selector
  ([selector] (.querySelector js/document selector))
  ([selector container] (.querySelector (select container) selector)))
(defmethod select :dom [node] node)

(defmulti select-all node-type)
(defmethod select-all :selector
  ([selector] (.querySelectorAll js/document selector))
  ([selector container] (.querySelectorAll (select container) selector)))
(defmethod select-all :dom [nodes] nodes)



(defn children [node]
  (filter #(= 1 (.-nodeType %))
          (.-childNodes (select node))))

(defn parent [node]
  (.-parentNode (select node)))



(declare canonicalize)


(defn append!
  "Make element last child of container.
   Returns live DOM node.
   > *container* CSS selector or live DOM node
   > *el* hiccup vector"
  [container el]
  (let [el (if (dom-element? el)
             el
             (build-dom-elem el))]
    (gdom/appendChild (select container) el)
    el))

(defn prepend!
  "Make element first child of container.
   Returns live DOM node.
   > *container* CSS selector or live DOM node
   > *el* hiccup vector"
  [container el]
  (let [el (if (dom-element? el)
             el
             (build-dom-elem el))]
    (gdom/insertChildAt (select container) el 0)
    el))

(defn remove!
  "Remove element from DOM and return it.
   > *el* CSS selector or live DOM node"
  [el]
  (gdom/removeNode (select el)))

(defn replace!
  "Replace live DOM node with a new one.
   > *old* CSS selector or live DOM node
   > *new* CSS selector, live DOM node, or hiccup vector"
  [old new]
  (let [new (condp = (node-type new)
              :dom new
              :hiccup (build-dom-elem new)
              :selector (select new))]
    (gdom/replaceNode new (select old))))

(defn style
  "Get or set inline element style.

   `(style el)`                map of inline element styles

   `(style el :keyword)`       value of style :keyword

   `(style el {:keyword val})` sets inline style according to map, returns element

   `(style el :keyword val)`   sets single style, returns element"
  ([el] (throw (js/Error. "TODO: return map of element styles")))
  ([el x] (match [x]
                 [(k :when keyword?)] (gstyle/getComputedStyle el (name k))
                 [(m :when map?)] (doseq [[k v] m] (style el k v)))
     el)
  ([el k v] (gstyle/setStyle el (name k)
                             (match [v]
                                    [s :when string?] s
                                    [n :when number?]
                                    (if (#{:height :width :top :left :bottom :right} (keyword k))
                                      (str n "px")
                                      n)))
     el))

(defn attr
  "Get or set element attributes.

   `(attr el)`                map of element attributes

   `(attr el :keyword)`       value of attr :keyword

   `(attr el {:keyword val})` sets element attributes according to map, returns element

   `(attr el :keyword val)`   sets single attr, returns element"
  ([el] (let [attrs (.-attributes el)]
          (into {} (for [i (range (.-length attrs))]
                     [(keyword  (.-name (aget attrs i)))
