kornelski / slip

Slip.js — UI library for manipulating lists via swipe and drag gestures
BSD 2-Clause "Simplified" License
2.44k stars 213 forks source link

Multiple drop targets #15

Open aronduby opened 10 years ago

aronduby commented 10 years ago

I'm working on a project that I think Slip would be perfect for, except I'm really looking for the ability to use multiple lists and to move items between them. Any suggestions on how to go about accomplishing that using Slip?

y-lohse commented 10 years ago

Hi, I implemented cross list reordering on a local version of slip, not sure if this is something @pornel would like contributed to this repo. It would need some refinement anyway.

I don't think it's possible without altering the core. I did it roughly in the following way:

One of the trickiest part is that slip takes the position and size of the moving node into consideration to position sibling nodes while reordering… but in a cross list reorder, the target list doesn't have that original node space, so it has to be created in some other way.

kornelski commented 10 years ago

Great writeup @y-lohse.

I originally designed it for mobile phones where usually only one column is visible at a time, which is why it's not a generic draggable-anything-anywhere library.

However, I'm all for extending the code to handle more cases, as long as the core use case isn't compromised (for example reordering within a single list should keep behavior of "locking" element horizontally and only moving vertically).

In the code there's states object. You could add a new state for dragging across lists there, and where the state is set this.setState(this.states.reorder) enable the new state based on Slip's configuration.

Can you describe your use-cases in more detail?

I'm wondering whether dragging between lists should be modelled as connecting instances of Slip together, or whether it needs to be generic to allow dragging anywhere. If it's supposed to allow dragging anywhere, should it use HTML5 drag'n'drop APIs to communicate with drop targets?

y-lohse commented 10 years ago

(for example reordering within a single list should keep behavior of "locking" element horizontally and only moving vertically).

I used a treshold of 20 (I think) pixels before unlocking the horizontal movement, so the behavior is still the same with a single list.

Can you describe your use-cases in more detail?

In my case it was clearly connecting 2 Slip instances together — the moved node is dropped into another list at a certain position, not into a generic dropping area.

innersky1 commented 10 years ago

I think connected lists and custom drop targets would be very nice features for this library. I'd use drage and drop between multiplbe vertically stacked lists on the phone. Another case would be using tabs, and dropping items on them (as a generic dropping area, but it could be on any drop target?) like the example of jQuery UI: http://jqueryui.com/sortable/#connect-lists-through-tabs

About using HTML5 drag'n'drop APIs: Does ios7 Safari already supports this?

I do like the idea of the treshold for unlocking the horizontal movement.

aronduby commented 10 years ago

My use case would definitely be connected lists. I have a list of just over 40 items which I need to do some slight reordering. The caveat in my case is everything needs to be in groups of 4. Swiping left/right would replace the item with a holder element, and when an item is moved into a group with a holder it would replace the holder element.

jenseralmeida commented 10 years ago

@y-lohse,

Can you share your changes? There is any fork or plan to apply it as official?

y-lohse commented 10 years ago

There you go. I did this a while ago, so:

humphreybc commented 10 years ago

@y-lohse This would be an awesome addition to Slip.js. Hopefully you get around to tidying it up and contributing it upstream. Do you have any further documentation on how to implement multiple lists with your forked implementation?

y-lohse commented 10 years ago

No, but basically, each instance of slip has a crossLists property which is an array. You have to push any communicating instances into that list.

var slipInstance1 = new Slip(myFirstList);
var slipInstance2 = new Slip(mySecondList);

slipInstance1.crossLists.push(slipInstance2);
slipInstance2.crossLists.push(slipInstance1);

Like I said, not very elegant. FWIW, jQueryUI uses a css selector to determine the lists that are connected.

I might have time in a couple of weeks to work on a cleaner implementation but it involves some serious API design decisions that I'd rather have @pornel approve beforehand :grinning:

buggedcom commented 7 years ago

@y-lohse Did you ever get round to porting your code over to the latest release?

y-lohse commented 7 years ago

Nope, sorry! I don't have the code anymore either.