User-sortable (drag and drop) iScroll list

1,453 views
Skip to first unread message

BrownieBoy

unread,
Jun 14, 2012, 11:09:48 PM6/14/12
to isc...@googlegroups.com

Guys,

A lengthy post, I'm afraid, but I've been tearing my hair out for days on this and would really appreciate some help!

I'm trying to have an iScroll list whose elements are also user-sortable via drag and drop.  I'm using jQueryUI's .sortable() functionality for that drag and drop stuff.  I'm also using the touch-punch library http://touchpunch.furf.com/ to translate touchscreen taps into their mouse equivalents where necessary. 

Now, just making the iScroll list doesn't work too well: as you drag the list element up and down, the list moves up and down with it!  I worked around that by disabling iScroll while the list is sortable and then re-enabling it when you've finished your drag and drop sorting of the list.

I've got it almost working but with one annoying bug: if you start a sort operation when the iScroll list is also partially scrolled down, then you can't drag a list element to the top of the list.  It's like the sorted list is frozen at the point where I disabled iScroll; it like it thinks that the *visible* to of the list is its *actual* top!

Here's some code to demonstrate.

JS Fiddle

http://jsfiddle.net/9TFvu/3/

Full screen (best for iPhone etc.):

http://bit.ly/M3FGap


Steps to reproduce problem:


1. Click on the Scrollable button to turn on iScroll for the list

2. Move up and down the list using that iScroll goodness.  Makes sure it's *not* at the top of the list and…

3. … click the Sortable button to disable iScroll and make the list sortable.

4. Grab the label test of a list item and drag it up and down.  Note how you can drag an list item below the visible bottom of the list and the list will scroll down to accommodate.  The same does *not* happen when you drag the item to the top of the list, and that's the problem.


Interesting control experiment with no iScroll involvment:

1. Refresh the browser to reload the demo

2. Scroll down the (now normal) list by 10 rows or so and then click on the Sortable button.

3. You can now drag list items down *and* up above the visible list and it will scroll in both directions.

iScroll is doing something to disable normal list behaviour but I'm not sure what it is.  I spotted that it sets the "overflow" property to "hidden" on the #wrapper element, which disables *all* scrolling on the sortable list.  However, I've removed that in my script and although it enabled scrolling again, I'm still left with my "down not up" problem.

BrownieBoy

unread,
Jun 18, 2012, 11:08:16 PM6/18/12
to isc...@googlegroups.com
I managed to work around my problems and now have a sortable list where items can be dragged "above" the scrollable area correctly.

The problem was there are two scrolling mechanisms at work here: the iScroll one (based on CSS) and the "normal" one (which I'll call "the JS one" from here on).  When I'm using iScroll then obviously the iScroll scrolling mechanism is at work.  When I am in Sort mode, however, I disabled the iScroll mechanism and call the jQuery.sortable(), at which point the JS scrolling mechanism comes into play.  At this point, however, the JS mechanism has no idea what the iScroll mechanism has been doing in terms of scrolling.  The JS mechanism has "lost its top point", so to speak.  

So, we need to reset it.  I do this by logging the current iScroll y-axis position, which I get from the iScroll object's "y" property: 

var currentY = $("#wrapper").scrollTop();

If that value is less than zero then the iScroll is not at its top, so I sent it back up to its top, like so:  

myUtils.myScroll.scrollTo(0, 0, 0, false); 

Now I can disable the iScroll object and call the code to enable the jQuery.sortable().  Having done that, I now send the JS scrolling mechanism back down to where the iScroll postion last was.  I do this via a call to jQuery.scrollTop(x), like so:

$("#wrapper").scrollTop(0 - currentY);

Voila!  I'm now in sort mode and drag and drop list items in either direction, and right to the top or bottom of the list.

When coming out of sort mode, I go through the same process in reverse.  This time, I get the currentY position from JS scrolling mechanism, by another call to jQuery.scrollTop(), only this time without a parameter.  I then feed that position to the iScroll mechanism to send it back to the last position that the JS mechanism was.

All this happens fast enough that the user shouldn't even see it.  It's clunky, but it appears to work.

Here's a JS Fiddle for the workaround version:

And here's a direct link, better for iPhone etc:





On Friday, 15 June 2012 13:09:48 UTC+10, BrownieBoy wrote:


Reply all
Reply to author
Forward
0 new messages