This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-15
Channels
- # adventofcode (121)
- # bangalore-clj (5)
- # beginners (46)
- # boot-dev (9)
- # cider (20)
- # cljs-dev (7)
- # cljsrn (1)
- # clojure (341)
- # clojure-austin (7)
- # clojure-greece (144)
- # clojure-india (3)
- # clojure-italy (5)
- # clojure-spain (1)
- # clojure-spec (34)
- # clojure-sweden (3)
- # clojure-uk (90)
- # clojurescript (24)
- # core-async (1)
- # core-logic (7)
- # cursive (108)
- # datascript (2)
- # datomic (39)
- # events (1)
- # fulcro (225)
- # graphql (8)
- # hoplon (86)
- # instaparse (12)
- # jobs-discuss (2)
- # jvm (4)
- # keechma (1)
- # lein-figwheel (2)
- # leiningen (12)
- # off-topic (26)
- # onyx (35)
- # other-languages (1)
- # pedestal (3)
- # planck (11)
- # re-frame (12)
- # reagent (12)
- # reitit (5)
- # spacemacs (48)
- # specter (29)
- # sql (2)
- # test-check (1)
- # unrepl (71)
@micha not a library, but i can show you 🙂
(h/defelem drag-wrap
"A drag and drop wrapper to sit between lists and items."
[{:keys [conn list item dropped-item]} children]
(let [new-item? (j/cell= (= item.data/new-item-id (:db/id item)))
dropped-item (or dropped-item (j/cell nil))
data-transfer-mime "text"
set-dragged-item! (fn [e i]
(-> e
.-originalEvent
.-dataTransfer
(.setData data-transfer-mime (pr-str i))))
event->dragged-item (fn [e]
(-> e
.-originalEvent
.-dataTransfer
(.getData data-transfer-mime)
cljs.reader/read-string))
drag-source? (j/cell false)
drag-target? (j/cell false)
drag-end! #(j/dosync
(reset! drag-source? false)
(reset! drag-target? false)
true)]
(h/div
; Drag source attributes.
; Must be the string "true" as this attribute is enumerated.
;
; Don't allow dummy/new items to be draggable.
:draggable (j/cell= (when-not new-item? "true"))
:data-drag-source drag-source?
; todo - replace with real styles.
:garden (j/cell=
(if (not new-item?)
{:cursor :move}
{:cursor :pointer}))
:dragstart #(do (-> % .-originalEvent .-dataTransfer (aset "effectAllowed" "move"))
(set-dragged-item! % @item)
(reset! drag-source? true)
true)
:dragend drag-end!
; Drag target attributes.
:data-drag-target (j/cell= (and drag-target? (not drag-source?)))
:dragenter #(do (.preventDefault %)
(reset! drag-target? true)
false)
:dragover #(do
(-> % .-originalEvent .-dataTransfer (aset "dropEffect" "move"))
(.preventDefault %)
(reset! drag-target? true)
false)
:dragleave #(do (reset! drag-target? false)
false)
:drop #(j/dosync
(.stopPropagation %)
(drag-end!)
(let [; The dropzone item might actually be a new item, in which
; case we just want to move the dropped item to the end of
; the list.
anchor-item (if @new-item?
(or (last @list) @item)
@item)]
(item-list.api/move-item-after! conn @list anchor-item (event->dragged-item %)))
(reset! dropped-item (event->dragged-item %))
false)
children)))
it works OK, but i haven't made a very nice animation/styles for it yet
and also ckeditor is too helpful, if i drag something onto the wysiwyg then it puts the raw dataTransfer data into the editor as EDN
dnd api is crazy
you serialise data from the thing being dragged and it gets passed to the thing being dropped onto
thank god for pr-str and read-string in cljs
the nice thing is that you can then drop that serialised data anywhere, including your desktop or other tabs/browser windows
or drop a file from your desktop into the page and receive it as serialised data
you will definitely experience some emotions working through this api >.<
well you say that, but think of google drive
it's pretty natural in that situation to want to drag things around outside the single browser tab
well i assume it works, lol
it seems like it should
yes definitely
and in order to make it ubiquitous you'd need to basically solve the clipboard problem, a universal serialization of arbitrary things
the general consensus seems to be that the native dnd api is weird and hard to work with >.<
although the extra events are handy
you get real drag events, rather than needing to try and reverse engineer something from raw mouse events
looks like there are some polyfills around too
^^ but it's a bit tooo wysiwyg friendly >.<
i think i can fix/disable this behaviour, just looking into it 🙂
:dragover #(do
(-> % .-originalEvent .-dataTransfer (aset "dropEffect" "move"))
(.preventDefault %)
(reset! drag-target? true)
false)
ah, yeah so thats an event on the dragged over element
in this context i have a list of things that can be dragged to re-arrange
so i need to put both the "thing being dragged" and "being dragged over/onto" events on all the items
the dataTransfer property has more than just the data in it, in this case i'm actually setting the "dropEffect"
which is literally just what it looks like
non-functional
the preventDefault is what you need to do to enable drag events, because the default behaviour is to disable drag events
:drop #(j/dosync
(.stopPropagation %)
(drag-end!)
(let [; The dropzone item might actually be a new item, in which
; case we just want to move the dropped item to the end of
; the list.
anchor-item (if @new-item?
(or (last @list) @item)
@item)]
(item-list.api/move-item-after! conn @list anchor-item (event->dragged-item %)))
(reset! dropped-item (event->dragged-item %))
false)
this is the end of the dragging, at the drop
that's where i'm actually extracting the data
but you could do that in different ways too, depending on what you're trying to achieve
well it's the only way to communicate between the thing being dragged and thing being dragged onto using the events
but you could probably do something with cells too
yeah, passing information is the standard integration point
actually it probably makes perfect sense if you wanted to drag an image from your desktop into a wysiwyg
but if you just want a self contained dnd with the events you could just hook some basic cells up
or across your app
you can drop onto anything
you might not want to maintain global state cells or many state cells if you have a lot of dnd
it could be easier to just handle the logic of "something just got dropped onto this element" like any other event handler
a flat list of identically structured items is really a special case of what the api can do
it could be handy if you were making a game, where basically anything can be dropped onto anything else
i really wouldn't call any of these apis "awesome"...
@micha Will you repost your DnD implementation. Just noticed the Slack log is not logging this channel since mid November 😞 https://clojurians-log.clojureverse.org/hoplon/index.html
What would be the easiest approach to getting drag and drop working with touch/multi-touch. My understanding is that there are significant differences between click events and touch events, and the touch events are not in Jquery by default. Do you generally need a special library or polyfill, etc?
Even if the native browser Api is wierd, would it be advisable to just use, or use raw touch events with Hoplon cells, as discussed above?
Maybe this is a sucessor to hammer.js to add touch events to jQuery https://github.com/benmajor/jQuery-Touch-Events
chromalchemy i think this is micha's gist: https://gist.github.com/micha/4855e90e3085c91768faf150ab0035c3
interact.js looks pretty slick. http://interactjs.io/ I'm not confident with js interop, so try to stick closely to jquery... any thoughts though?
a couple years ago micha made a touch app w/ hoplon, i think with hammer.js or jq touch. and the integration point was do!, he seemed happy with it iirc
Was that related to this https://github.com/tailrecursion/hoplon.hammerjs/blob/master/src/tailrecursion/hoplon/hammerjs.cljs ? Here it is using on!