Skip to content

Instantly share code, notes, and snippets.

@selfsame
Created January 26, 2016 21:16
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 selfsame/12c5ae9179b86760d1e0 to your computer and use it in GitHub Desktop.
Save selfsame/12c5ae9179b86760d1e0 to your computer and use it in GitHub Desktop.
(defui Main
static om/IQueryParams
(params [this] {})
static om/IQuery
(query [this]
`[:item/filters
:image/by-path
{:editing ~(om/get-query Item) }
{:inventory ~(om/get-query Item) }])
Object
(render [this]
(let [props (om/props this)
params (om/get-params this)
items (:inventory props)]
(html
(<div#sidebar
(<h1 "Filter")
(map
(fn [fk]
(let [active (if (get (:item/filters props) fk) true false)]
(<label.toggle (str (clj->js fk))
(class ({true "active" false ""} active))
(<input (type "checkbox") (checked active)
(onChange [_] (om/transact! this
`[(inventory/filter! ~(assoc props :toggle/filter fk))]))))))
(keys item-filters))
(<span (str (count items)) (style {:color :yellow :font-size "1.3em"}))
(<h1 "image paths")
(<div.image-list
(map #(<p (str %)) (keys (:image/by-path props)))))
(<div#inventory (map item items))
(if (first (:editing props))
(<div#edit.editing
(<button "save" (onClick [e] (om/transact! this `[(save/edit ~props) :editing])))
(editor (:editing props))))))))
(def valid-attribute?
#{'accept 'acceptCharset 'accessKey 'action 'allowFullScreen 'allowTransparency 'alt 'async 'autoComplete 'autoFocus
'autoPlay 'capture 'cellPadding 'cellSpacing 'challenge 'charSet 'checked 'classID 'className 'colSpan 'cols 'content
'contentEditable 'contextMenu 'controls 'coords 'crossOrigin 'data 'dateTime 'default 'defer 'dir 'disabled 'download
'draggable 'encType 'form 'formAction 'formEncType 'formMethod 'formNoValidate 'formTarget 'frameBorder 'headers 'height
'hidden 'high 'href 'hrefLang 'htmlFor 'httpEquiv 'icon 'id 'inputMode 'integrity 'is 'keyParams 'keyType 'kind 'label
'lang 'list 'loop 'low 'manifest 'marginHeight 'marginWidth 'max 'maxLength 'media 'mediaGroup 'method 'min 'minLength
'multiple 'muted 'name 'noValidate 'nonce 'open 'optimum 'pattern 'placeholder 'poster 'preload 'radioGroup 'readOnly
'rel 'required 'reversed 'role 'rowSpan 'rows 'sandbox 'scope 'scoped 'scrolling 'seamless 'selected 'shape 'size 'sizes
'span 'spellCheck 'src 'srcDoc 'srcLang 'srcSet 'start 'step 'style 'summary 'tabIndex 'target 'title 'type 'useMap 'value
'width 'wmode 'wrap 'onTouchMove 'onKeyDown 'onLoadedData 'onInput 'onChange 'onDragStart 'onDrop 'onContextMenu 'onFocus
'onClick 'onCut 'onTouchEnd 'onDrag 'onDragExit 'onDragEnter 'onTouchCancel 'onSubmit 'onTouchStart 'onBlur 'onWheel 'onPaste
'onHover 'onKeyUp 'onKeyPress 'onDragOver 'onDragLeave 'onDoubleClick 'onDragEnd 'onCopy 'onScroll 'onLoad 'onAbort 'onCanPlay
'onCanPlayThrough 'onDurationChange 'onEmptied 'onEncrypted 'onEnded 'onError 'onLoadedMetadata 'onLoadStart 'onPause 'onPlay
'onPlaying 'onProgress 'onRateChange 'onSeeked 'onSeeking 'onStalled 'onSuspend 'onTimeUpdate 'onVolumeChange 'onWaiting 'onSelect
'onMouseDown 'onMouseEnter 'onMouseLeave 'onMouseMove 'onMouseOut 'onMouseOver 'onMouseUp 'onCompositionEnd 'onCompositionStart
'onCompositionUpdate 'class 'key 'ref })
(defn attr-merge [a b]
(cond (string? b) b
(vector? b) (vec (concat a b))
(sequential? b) (concat a b)
:else (conj a b)))
(defn attr-post [m]
(if (empty? (:class m)) (dissoc m :class)
(assoc (dissoc m :class) :className
`(~'clj->js (apply str (interpose " " ~(:class m)))))))
(defn meta-use [form]
(let [mm (mapv #(:_html (meta %)) form)]
(if-not (first mm) form
`(~(first form)
(~'clj->js ~(attr-post (apply merge-with attr-merge (filter map? mm))))
~@(filter #(not= '_nil %) (rest form))))))
(defn -attr [form]
(let [attr (first form)]
(cond (= 'class attr)
(vec (rest form))
(re-find #"^on[A-Z]" (str attr))
(if (vector? (first (rest form)))
`(fn ~@(rest form))
(first (rest form)))
:else (first (rest form)))))
(defn soup [s]
(when-let [tag (last (re-find #"\<([\w-_]+)" s))]
(let [id (last (re-find #"\#([\w-_]+)" s))
cs (mapv last (re-seq #"\.([\w-_]+)" s))]
(with-meta (symbol (str "om.dom/" tag))
{:_html (conj {} (if id {:id id}) (if (first cs) {:class cs}))}))))
(defn html-recur [form]
(cond (symbol? form) (or (soup (str form)) form)
(vector? form) (meta-use (mapv html-recur form))
(list? form) (cond (valid-attribute? (first form))
(with-meta '_nil {:_html {(keyword (first form)) (-attr form)}})
:else (meta-use (map html-recur form)))
(map? form) form ;(with-meta '_nil form)
:else form))
(defmacro html [& body]
(let [forms (html-recur body)]
`~(if (= 1 (count forms))
(first forms)
(concat ['om.dom/div {}] forms))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment