anseki / plain-draggable

The simple and high performance library to allow HTML/SVG element to be dragged.
https://anseki.github.io/plain-draggable/
MIT License
765 stars 96 forks source link

Containment issues #32

Closed NathanaelA closed 5 years ago

NathanaelA commented 5 years ago

So here is the full use case;

  1. I want all draggable items to stay inside of a div that is wrapped in an outer scrollable div.
  2. I would like the autoScroll to continue to work (like it does now!)
  3. I want to be able to put additional containment on some of the draggable items, so that "line 1" does not go past "line 2" and "line 2" cannot come above "line 1". In my local project I have code to recalculate the containment on every drag; so that if you move line1 then line2's containment is updated to now know where the top is now at. However the containment system seems to have issues when inside a scrollable item. It seems like coordinates must change from the scroll, and so then the object is moved.
  4. I would love to be able to add additional items that aren't contained but can snap to those lines. (I believe this is already doable; just haven't done the math -- but it is possible that the snap system might have issues with the scrollable div)

Primary issue: How do I contain Line 1 so it can't go below Line 2. Contain Line 2 so it can't go above line 1, while allowing the div to scroll.

https://jsfiddle.net/yoc3r1mv/8/

Issues so far found: [ ] - Auto-movement of contained items: https://github.com/anseki/plain-draggable/issues/30 [x] - leftTop causes draggable to be outside of the constraints of the parent container https://github.com/anseki/plain-draggable/issues/31

anseki commented 5 years ago

Hi @NathanaelA, thank you for the comment. So, I'm confused. You created three new issues repeatedly. Are those related to this issue? Also, you closed only #31. Was that already solved? Basically, you should not create duplicated issues, also you should not create an issue that contains multiple topics.

Sorry, my English is poor. I couldn't understand relating between those issues. Could you check those please?

NathanaelA commented 5 years ago

This is both a issue and the top level bug to track all the other sub-issues I found relating to what I need to do. If you can show me how to solve this issue, I would be very happy. :grinning:

When I created this issue; I had 4 or 5 issues that I was going to report all related to doing this. Several of them I managed to figure out workarounds or my misunderstanding while creating fiddles for them. So they weren't saved/created. :grinning: #31 I also finally figured out later, so I closed it.

So #30 and this one are still valid issues. #30 is I believe a bug for sure. This issue is probably more that I'm not sure how to deal with the containment in a scroll-able div.

What language is your native language?

anseki commented 5 years ago

Thank you for the explaining. That is...

Are these right? In other words, #32 should be closed and #30 should be solved.

NathanaelA commented 5 years ago

30 and #32 are both issues.

anseki commented 5 years ago

What's the difference between #30 and #32?

NathanaelA commented 5 years ago

30 is specifically the issue where if you scroll a div with a draggable with a containment; the draggable moves by itself. (You will see "Line 1" move if you scroll the div to the bottom)

32, is if #30 is fixed; how do you create a containment system that can contain the object compared to other draggables; since the coordinate system for all draggables change during scrolling. They use the same demo just because it is easier to see the issue.

anseki commented 5 years ago

I see. Thank you for the explaining. You can change the containment dynamically. However using return value of onDrag event handler is more easy maybe. https://anseki.github.io/plain-draggable/#options-ondrag

NathanaelA commented 5 years ago

Problem is you CAN'T change the containment dynamically if you are using the autoScroll, the autoScroll will automatically scroll which of course then changes the coordinate system underneath you and causes the containment to be wrong on all objects that have containment.

I've even tried attaching to the div's scroll event -- doesn't help because it doesn't fire quickly/frequently enough to make sure that we can change the containment dynamically fast enough before the containment system messes up the location of all the objects during scroll.


As for the onDrag event, this might work...

anseki commented 5 years ago

Uhmm... I can't understand that. Could you show me an example that tries to change the containment?

NathanaelA commented 5 years ago

Tested the onDrag and it won't work either.

Locked

Ok, so this gif shows three things.

So I start on the Footer week -- I figured out a way to do containment only when autoScroll is turned off; so the Footer week has autoScroll turned off. And so you can see how it works, and it works well. :grinning: (Very happy with this part, this is exactly what I want....)


Now the Final Summary has autoScroll on, because it is the very last "Line". You will notice it starts to scroll down when I grab it, which is correct/good.

And as I am bringing it back up the first time it stops midway. This is where the onDrag handler thought the PlainDraggable footername.top was at. So the calculation on the footerName.top was not updated fast enough during the autoScroll so that the moment the following code compared the two plainDraggable's top; it had the wrong coordinate and then returned false. (The +21 is the height of the line)

// These are both PlainDraggable objects
if (footerName.top + 21 >= finalSummary.top) {
   return false;
}

The above shows the out-of-sync issue.


Next I drop the draggable and re-pick it up; and it re-calculates its top vs the other top and lets me move it to where the footerName is at. But again, because we return false this stops all drag movement. I want this to act just like the Footer week did where I can move back down, I don't want my drag to actually stop moving all directions; I only want my drag to not go up anymore; but to allow me to go back down....

NathanaelA commented 5 years ago

If I change my code to try and allow me to move down rather than forcing stopping the move:

                      if (footerName.top + 21 >= finalSummary.top) {
                          finalSummary.top = footerName.top + 22;
                          return false;
                      }

You see this effect: Jitter

This is why I abandoned trying to use onDrag initially; I couldn't seem to figure out a way around the jitter or forcing them to stop the drag and start another one...

anseki commented 5 years ago

Sorry, I couldn't understand without the code. In your fiddle, you want to limit the position of "Line 2" to under "Line 1". Right?

NathanaelA commented 5 years ago

Yes, I want Line 2 to be contained below Line 1 and Line 1 to be contained above line 2 Each time you move either of them the containment has to be updated. AutoScroll on both lines should enabled linked to the scrolling div like https://jsfiddle.net/yoc3r1mv/8/

anseki commented 5 years ago

Like this? https://jsfiddle.net/qp36yLnd/ Note that this may be incompletely.

NathanaelA commented 5 years ago

https://jsfiddle.net/qp36yLnd/ -- -Doesn't work; still very broken. Move Line 1 down, it will cause Line 2 to move. Move Line 1 down rapidly, it will cause it merge with line 2

See: Peek 2019-08-23 06-13

In addition, you added additional Markup, can we do this without any extra html markup?

anseki commented 5 years ago

You misunderstood again and again... As I said, that may be incompletely. The example can limit the position of "Line 2" to under "Line 1". Right? The controlling "Line 1" is your task, also adjusting those when the element is moved. Because that is your app, not mine, I don't know your app. Of course you can that without additional element.

NathanaelA commented 5 years ago

I don't need you to know my app. :grinning: The jsfiddle, I provided has the exact simple markup two lines ( https://jsfiddle.net/yoc3r1mv/8/ ) No extra html, AutoScroll enabled. Line 1 cannot pass line 2, line 2 cannot pass line 1.

Rect Works -> AutoScroll disabled. Rect Fails -> AutoScroll enabled.

I don't believe it is possible with the Rect system. Do you agree?

Re-reading your docs it does seem to be clear that the Rect system base is document. So this is my misunderstanding, I thought Rect system was based on the parent of the draggable...

NathanaelA commented 5 years ago

Based on the answers also provided in #30 - I think we can close this one. Thank you for your time!

anseki commented 5 years ago

It's OK. You should understand that the issue doesn't exist and the Rect works correctly. For example: https://jsfiddle.net/uw5njf0q/ I'm happy if I could help you. :smile:

NathanaelA commented 5 years ago

I have a solution based on the extra element in #30 -- so you don't need to worry about it. :grinning: But for anyone else who reads this thread, the above example still doesn't work. the "line 1" will still push "line 2" down.

So using the extra element; to wrap the area you want to keep the draggable in, and then using that as the containment works and only adds a single extra hidden div to the dom. I just configure and assign the div in the onDragStart and reset the containment back to the entire document onDragEnd

anseki commented 5 years ago

Ah, I thought that the containment should be updated when the element is moved. That is, I thought that the "Line 1" pushing down the "Line 2" is correct behavior. This is, just only I don't know your app. Of course you can adjust that. And I think that you found the your misunderstanding, also the library and Rect work correctly.

BTW, the example don't need margin. https://jsfiddle.net/d7nvajub/

NathanaelA commented 5 years ago

I'm not sure you saved the above jsFiddle; it looks identical to the one before it.

Line1 still pushes Line2 down. The requirement (which I fixed in my project, using an extra div you showed me in #30 :grinning: ) is that Line 1 stops at Line 2 and Line 2 stops at line 1. Moving either line will update the constraints so that Line 1 will stop at the current/new location that Line 2 is at and Line 2 would stop at the current/new Line 1 location.

anseki commented 5 years ago

You misunderstood again, again and again... As I said, I updated the example about the margin. Also, of course I didn't change about "Line 1" pushing down "Line 2" because I thought that is correct behavior as I said. I'm sorry if your misunderstanding was made by my poor English. Please understand I don't know your app and I think I don't have to change the example because your issues were already solved.

I think that you found the your misunderstanding, also the library and Rect work correctly. Right? Do you mean that an issue something still exist? Or, do you want another example?

NathanaelA commented 5 years ago

No, I don't need another example. :grinning: I was trying to clarify for anyone else who see this issue and thinks that the demo would limit line 1 & line 2, that it doesn't, so that they don't get confused. :-)

anseki commented 5 years ago

:smile: