You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
c4k-common/src/main/cljs/dda/c4k_common/browser.cljs

195 lines
5.1 KiB
Clojure

(ns dda.c4k-common.browser
(:require
[clojure.string :as st]
[clojure.spec.alpha :as s]
[expound.alpha :as expound]
[orchestra.core :refer-macros [defn-spec]]
[hickory.render :as hr]))
(def js-object? any?)
(defn-spec print-debug string?
[sth string?]
(print "debug " sth)
sth)
(defn-spec get-element-by-id js-object?
[name string?]
(-> js/document
(.getElementById name)))
(s/def ::deserializer fn?)
(s/def ::optional boolean?)
(def dom-function-parameter (s/keys :opt-un [::deserializer ::optional]))
(defn-spec get-content-from-element js-object?
[name string?]
(-> (get-element-by-id name)
(.-value)))
(defn-spec deserialize-content js-object?
[content string?
deserializer ::deserializer
optional ::optional]
(cond
(and optional (st/blank? content))
nil
:else
(apply deserializer [content])))
(defn-spec get-deserialized-content js-object?
[name string?
& {:keys [deserializer optional]
:or {deserializer identity optional false}} dom-function-parameter]
(-> (get-content-from-element name)
(deserialize-content deserializer optional)))
(defn-spec set-validation-result! js-object?
[name string?
validation-result js-object?]
(-> (get-element-by-id (str name "-validation"))
(.-innerHTML)
(set! validation-result))
(-> (get-element-by-id name)
(.setCustomValidity validation-result))
validation-result)
(defn-spec validate! js-object?
[name string?
spec js-object?
& {:keys [deserializer optional]
:or {deserializer identity optional false}} dom-function-parameter]
(let [content (get-deserialized-content name :optional optional :deserializer deserializer)]
(if (or (and optional (st/blank? content))
(s/valid? spec content))
(set-validation-result! name "")
(set-validation-result! name
(expound/expound-str spec content {:print-specs? false})))))
(defn-spec set-output! js-object?
[input string?]
(-> js/document
(.getElementById "output")
(.-value)
(set! input)))
(defn-spec set-form-validated! js-object?
[]
(-> (get-element-by-id "form")
(.-classList)
(.add "was-validated")))
(defn-spec ^{:deprecated "0.4"} set-validated! js-object?
[]
(set-form-validated!))
(defn-spec create-js-obj-from-html js-object?
[html-string string?]
(-> js/document
.createRange
(.createContextualFragment html-string)))
(defn-spec append-to-c4k-content js-object?
[js-obj js-object?]
(-> (get-element-by-id "c4k-content")
(.appendChild js-obj)))
(defn-spec append-hickory js-object?
[hickory-obj map?]
(-> hickory-obj
(hr/hickory-to-html)
(create-js-obj-from-html)
(append-to-c4k-content)))
(defn-spec generate-feedback-tag map?
[id string?]
{:type :element
:attrs {:class "invalid-feedback"}
:tag :div
:content [{:type :element
:attrs {:id (str id "-validation")}
:tag :pre
:content nil}]})
(defn-spec generate-label map?
[id-for string?
label string?]
{:type :element
:attrs {:for id-for :class "form-label"}
:tag :label
:content [label]})
(defn-spec generate-br map?
[]
{:type :element, :attrs nil, :tag :br, :content nil})
(defn-spec generate-input-field map?
[id string?
label string?
default-value string?]
[(generate-label id label)
{:type :element
:attrs {:class "form-control" :type "text" :name id :id id :value default-value}
:tag :input
:content nil}
(generate-feedback-tag id)
(generate-br)])
(defn-spec generate-text-area map?
[id string?
label string?
default-value string?
rows pos-int?]
[(generate-label id label)
{:type :element
:attrs {:name id :id id :class "form-control" :rows rows}
:tag :textarea
:content [default-value]}
(generate-feedback-tag id)
(generate-br)])
(defn-spec generate-button map?
[id string?
label string?]
[{:type :element
:attrs {:type "button", :id id, :class "btn btn-primary"}
:tag :button
:content [label]}
(generate-br)])
(defn-spec generate-output vector?
[id string?
label string?
rows pos-int?]
[{:type :element,
:attrs {:id id},
:tag :div,
:content [{:type :element
:attrs {:for "output", :class "form-label"}
:tag :label, :content [label]}
{:type :element, :attrs {:name "output",
:id "output",
:class "form-control",
:rows rows},
:tag :textarea, :content []}]}
(generate-br)])
(defn-spec generate-needs-validation map?
[]
{:type :element,
:attrs {:class "needs-validation", :id "form"},
:tag :form,
:content []})
(defn-spec generate-group map?
[name string?
content any?]
[{:type :element
:tag :div
:attrs {:class "rounded border border-3 m-3 p-2"}
:content [{:type :element
:tag :b
:attrs {:style "z-index: 1; position: relative; top: -1.3rem;"}
:content name}
{:type :element
:tag :fieldset
:content content}]}])