# Drag and Drop through IDs

**URL:** <https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702>\
**Category:** Request Feedback\
**Created:** [May 27, 2019, 8:40pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702 "2019-05-27T20:40:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![theotherben](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/theotherben/32/2186_2.png) [@theotherben](https://discourse.elm-lang.org/u/theotherben)\
**Post date:** [May 27, 2019, 8:40pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/1 "2019-05-27T20:40:24Z")

</div>

I’m trying to build a drag and drop library for Elm that:

- Supports touch
- Allows users to subscribe to messages all along the drag/drop lifecycle: `dragStart`, `dragMove`, `draggedOver`, `dropped`.
- Doesn’t require ports
- Doesn’t use the [HTML5 Drag and Drop API](https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html)
- Doesn’t put functions in the Model or Msg.

To support touch without ports, I’m trying to use [`Browser.Dom.getElement`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#getElement), which works using string IDs. So, I need to be able to query the bounds for every single drop target so I can tell what the user has dragged over. This is where things get tricky: how do I get the full list of IDs to query?

My best guess so far is to store a `Dict` that maps IDs to events. The user would then have to initialize this dictionary in `init` or modify it in `update` if things change:

```auto
dropTargets: Dict String (EventHandlers msg)
type alias EventHandlers msg = {
  onDragEnter: msg,
  onDragLeave: msg,
  onDroppedOn: msg
}

```

This has some drawbacks: the user would have to always have a list of _all_ of the drop targets and would have to pair their IDs up with the objects they end up rendering. Ideally, I would like to have this just be part of the `view` function, similar to other event registration.

```auto
dropTarget: String -> List (DropTargetEvents msg) -> Html msg -> Html msg
dropTarget id events element =
  -- ...

type DropTargetEvents msg =
	| OnDragEnter msg
	| OnDragLeave msg
	OnDroppedOver msg

```

Then, each individual element could handle the hit-testing itself. I wouldn’t need a dictionary of all of the IDs. The only catch with this is that I don’t think there’s an event that each element could listen to in order to get the current touch location.

I’ve been looking at this enough that my thinking is fuzzy here; does anyone have any thoughts? Is the dictionary approach reasonable?

---

<div class="post-metadata">

**Author:** ![mattpiz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/mattpiz/32/860_2.png) [@mattpiz](https://discourse.elm-lang.org/u/mattpiz)\
**Post date:** [May 28, 2019, 9:40pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/2 "2019-05-28T21:40:34Z")

</div>

> [@theotherben](#):
>
> To support touch without ports

Hi, I’m not sure what you mean by that. You can attach touch events to elements too (have look at what I did in the code of [elm-pointer-events](https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/latest/Html-Events-Extra-Touch)).

I’ve an Html5 dnd implementation there also but as you know, it isn’t ideal, even if I clearly opinionated my API to reduce to minimum the possible errors using it.

Out of curiosity, there seems to be a lot of drag and drop libraries in elm package (search “drag”). Have you tried them, which one are closer to what you are looking for?

---

<div class="post-metadata">

**Author:** ![theotherben](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/theotherben/32/2186_2.png) [@theotherben](https://discourse.elm-lang.org/u/theotherben)\
**Post date:** [May 28, 2019, 10:39pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/3 "2019-05-28T22:39:39Z")

</div>

I’m definitely close enough to the problem that I’m sure I’m not communicating about it clearly. 🙂 It’s hard to write in a way that’s to-the-point while still laying out all of the things I’ve tried!

I actually first started with your library! I really appreciated the opinionated API. The catches I ran into were:

- HTML5 Drag and Drop doesn’t work [at all](https://caniuse.com/#feat=dragndrop) in Android.
- There are no `touch` equivalents of `mouseenter` and `mouseleave`, which I use to check what you’re dragging over.
- The `elm-pep` polyfill similarly doesn’t implement `pointerenter` and `pointerleave`. Maybe I should have thought about adding that to the polyfill instead?

The other libraries I looked at were:

- [dnd-list](https://package.elm-lang.org/packages/annaghi/dnd-list/latest/) – great library for sortable lists! My use cases are a little different – closer to Chess, for example.
- [elm-dnd](https://package.elm-lang.org/packages/ir4y/elm-dnd/latest/) – works great for its use case, but I needed access to more lifecycle events (dragStart, for example) and the ability to integrate some animations.
- The [other](https://package.elm-lang.org/packages/arsduo/elm-dom-drag-drop/latest/) [ones](https://package.elm-lang.org/packages/norpan/elm-html5-drag-drop/latest/) also used HTML5 drag and drop, which rules out Android 🙁

My current implementation uses ports to simulate `touchenter` and `touchleave`. I call out to a JS helper to call [elementsFromPoint()](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/elementsFromPoint), filter for elements that have a class that I’ve attached in Elm, and then dispatch a `touchenter` event on them.

However, I’d like to do the hit testing in Elm, to remove the need for ports/polyfills. I believe the only way to get element bounds in Elm is by attaching unique IDs to them and then calling out to `Browser.Dom.getElement`. Having the hit testing done in Elm also makes it easier to do animations – for example, having the object “snap” into place when you release it. This leads to the question in the original post – how can I make it easy for users to attach IDs to their elements?

Thanks for the time, mattpiz – I have a lot of respect for the problem you were solving with `elm-pointer-events` now that I’ve navigated the morass of browser compatibility that is touch, pointer events, and the drag API.

---

<div class="post-metadata">

**Author:** ![mattpiz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/mattpiz/32/860_2.png) [@mattpiz](https://discourse.elm-lang.org/u/mattpiz)\
**Post date:** [May 29, 2019, 8:56am UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/4 "2019-05-29T08:56:50Z")

</div>

> [@theotherben](#):
>
> There are no `touch` equivalents of `mouseenter` and `mouseleave` , which I use to check what you’re dragging over.

Ha I see, if I remember correctly, I did not put those in the API because they were poorly supported by browsers, probably not standard even. Probably why they didn’t make it into the polyfill too. Though these days I feel like the polyfil might not be needed anymore? (It’s in safari TP, and for other OSs we can ask user to use another browser mostly)

So back to your original issue, I feel like it’s a tough problem to have this ergonomic for users, not keeping track of ids manually. To be honest I’m not doing much elm these days (having a thesis to end ^^). But I think others might have better ideas with a concrete layout example. Something like a minimalist Ellie example with a layout similar to what you’d be drag and dropping around.

---

<div class="post-metadata">

**Author:** ![theotherben](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/theotherben/32/2186_2.png) [@theotherben](https://discourse.elm-lang.org/u/theotherben)\
**Post date:** [May 29, 2019, 5:09pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/5 "2019-05-29T17:09:35Z")

</div>

Good call – That should make the problem a bit more concrete.

Also, I didn’t notice that `pointer-events` made it into Safari TP! Of course, it’s not yet listed on iOS Safari. Dammit, browsers.

---

<div class="post-metadata">

**Author:** ![annaghi](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/annaghi/32/1814_2.png) [@annaghi](https://discourse.elm-lang.org/u/annaghi)\
**Post date:** [May 30, 2019, 12:08pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/6 "2019-05-30T12:08:20Z")

</div>

I would like to confirm, I am interested in the problem, but I do not understand yet. If you put effort and time in an example, I will check it.

> [@theotherben](#):
>
> My use cases are a little different – closer to Chess, for example.

I have built a demo game: [Knight’s tour](https://annaghi.github.io/dnd-list/gallery/knight), perhaps you can get some idea from there.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [June 9, 2019, 12:08pm UTC](https://discourse.elm-lang.org/t/drag-and-drop-through-ids/3702/7 "2019-06-09T12:08:21Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
