mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 23:01:37 +02:00
258 lines
5.2 KiB
Clojure
258 lines
5.2 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
|
;; defined by the Mozilla Public License, v. 2.0.
|
|
;;
|
|
;; Copyright (c) 2020 UXBOX Labs SL
|
|
|
|
(ns app.util.dom
|
|
(:require
|
|
[app.common.exceptions :as ex]
|
|
[app.common.geom.point :as gpt]
|
|
[app.util.object :as obj]
|
|
[cuerdas.core :as str]
|
|
[goog.dom :as dom]))
|
|
|
|
;; --- Deprecated methods
|
|
|
|
(defn event->inner-text
|
|
[e]
|
|
(.-innerText (.-target e)))
|
|
|
|
(defn event->value
|
|
[e]
|
|
(.-value (.-target e)))
|
|
|
|
(defn event->target
|
|
[e]
|
|
(.-target e))
|
|
|
|
|
|
(defn classnames
|
|
[& params]
|
|
(assert (even? (count params)))
|
|
(str/join " " (reduce (fn [acc [k v]]
|
|
(if (true? (boolean v))
|
|
(conj acc (name k))
|
|
acc))
|
|
[]
|
|
(partition 2 params))))
|
|
|
|
|
|
;; --- New methods
|
|
|
|
(defn get-element-by-class
|
|
([classname]
|
|
(dom/getElementByClass classname))
|
|
([classname node]
|
|
(dom/getElementByClass classname node)))
|
|
|
|
(defn get-element
|
|
[id]
|
|
(dom/getElement id))
|
|
|
|
(defn stop-propagation
|
|
[e]
|
|
(when e
|
|
(.stopPropagation e)))
|
|
|
|
(defn prevent-default
|
|
[e]
|
|
(when e
|
|
(.preventDefault e)))
|
|
|
|
(defn get-target
|
|
"Extract the target from event instance."
|
|
[event]
|
|
(.-target event))
|
|
|
|
(defn get-parent
|
|
[dom]
|
|
(.-parentElement ^js dom))
|
|
|
|
(defn get-value
|
|
"Extract the value from dom node."
|
|
[node]
|
|
(.-value node))
|
|
|
|
(defn get-attribute
|
|
"Extract the value of one attribute of a dom node."
|
|
[node attr-name]
|
|
(.getAttribute node attr-name))
|
|
|
|
(def get-target-val (comp get-value get-target))
|
|
|
|
(defn click
|
|
"Click a node"
|
|
[node]
|
|
(.click node))
|
|
|
|
(defn get-files
|
|
"Extract the files from dom node."
|
|
[node]
|
|
(array-seq (.-files node)))
|
|
|
|
(defn checked?
|
|
"Check if the node that represents a radio
|
|
or checkbox is checked or not."
|
|
[node]
|
|
(.-checked node))
|
|
|
|
(defn valid?
|
|
"Check if the node that is a form input
|
|
has a valid value, against html5 form validation
|
|
properties (required, min/max, pattern...)."
|
|
[node]
|
|
(.-valid (.-validity node)))
|
|
|
|
(defn clean-value!
|
|
[node]
|
|
(set! (.-value node) ""))
|
|
|
|
(defn set-value!
|
|
[node value]
|
|
(set! (.-value node) value))
|
|
|
|
(defn select-text!
|
|
[node]
|
|
(.select ^js node))
|
|
|
|
(defn ^boolean equals?
|
|
[node-a node-b]
|
|
(.isEqualNode ^js node-a node-b))
|
|
|
|
(defn get-event-files
|
|
"Extract the files from event instance."
|
|
[event]
|
|
(get-files (get-target event)))
|
|
|
|
(defn create-element
|
|
([tag]
|
|
(.createElement js/document tag))
|
|
([ns tag]
|
|
(.createElementNS js/document ns tag)))
|
|
|
|
(defn set-html!
|
|
[el html]
|
|
(set! (.-innerHTML el) html))
|
|
|
|
(defn append-child!
|
|
[el child]
|
|
(.appendChild el child))
|
|
|
|
(defn get-first-child
|
|
[el]
|
|
(.-firstChild el))
|
|
|
|
(defn get-tag-name
|
|
[el]
|
|
(.-tagName el))
|
|
|
|
(defn get-outer-html
|
|
[el]
|
|
(.-outerHTML el))
|
|
|
|
(defn get-inner-text
|
|
[el]
|
|
(.-innerText el))
|
|
|
|
(defn query
|
|
[el query]
|
|
(.querySelector el query))
|
|
|
|
(defn get-client-position
|
|
[event]
|
|
(let [x (.-clientX event)
|
|
y (.-clientY event)]
|
|
(gpt/point x y)))
|
|
|
|
(defn get-offset-position
|
|
[event]
|
|
(let [x (.-offsetX event)
|
|
y (.-offsetY event)]
|
|
(gpt/point x y)))
|
|
|
|
(defn get-client-size
|
|
[node]
|
|
{:width (.-clientWidth ^js node)
|
|
:height (.-clientHeight ^js node)})
|
|
|
|
(defn get-bounding-rect
|
|
[node]
|
|
(let [rect (.getBoundingClientRect ^js node)]
|
|
{:left (.-left ^js rect)
|
|
:top (.-top ^js rect)
|
|
:right (.-right ^js rect)
|
|
:bottom (.-bottom ^js rect)
|
|
:width (.-width ^js rect)
|
|
:height (.-height ^js rect)}))
|
|
|
|
(defn get-window-size
|
|
[]
|
|
{:width (.-innerWidth ^js js/window)
|
|
:height (.-innerHeight ^js js/window)})
|
|
|
|
(defn focus!
|
|
[node]
|
|
(.focus node))
|
|
|
|
(defn fullscreen?
|
|
[]
|
|
(cond
|
|
(obj/in? js/document "webkitFullscreenElement")
|
|
(boolean (.-webkitFullscreenElement js/document))
|
|
|
|
(obj/in? js/document "fullscreenElement")
|
|
(boolean (.-fullscreenElement js/document))
|
|
|
|
:else
|
|
(ex/raise :type :not-supported
|
|
:hint "seems like the current browset does not support fullscreen api.")))
|
|
|
|
(defn ^boolean blob?
|
|
[v]
|
|
(instance? js/Blob v))
|
|
|
|
(defn create-blob
|
|
"Create a blob from content."
|
|
([content]
|
|
(create-blob content "application/octet-stream"))
|
|
([content mimetype]
|
|
(js/Blob. #js [content] #js {:type mimetype})))
|
|
|
|
(defn revoke-uri
|
|
[url]
|
|
(js/URL.revokeObjectURL url))
|
|
|
|
(defn create-uri
|
|
"Create a url from blob."
|
|
[b]
|
|
{:pre [(blob? b)]}
|
|
(js/URL.createObjectURL b))
|
|
|
|
(defn set-css-property [node property value]
|
|
(.setProperty (.-style ^js node) property value))
|
|
|
|
(defn capture-pointer [event]
|
|
(-> event get-target (.setPointerCapture (.-pointerId event))))
|
|
|
|
(defn release-pointer [event]
|
|
(-> event get-target (.releasePointerCapture (.-pointerId event))))
|
|
|
|
(defn get-root []
|
|
(query js/document "#app"))
|
|
|
|
(defn ^boolean class? [node class-name]
|
|
(let [class-list (.-classList ^js node)]
|
|
(.contains ^js class-list class-name)))
|
|
|
|
(defn get-user-agent []
|
|
(.-userAgent js/navigator))
|
|
|
|
(defn active? [node]
|
|
(= (.-activeElement js/document) node))
|
|
|
|
(defn get-data [^js node ^string attr]
|
|
(.getAttribute node (str "data-" attr)))
|