7

Scrolling a div that is within a .sortable() container will start dragging the div when you release the scrollbar

In the fiddle, there are 3 different sortables, 1 of them is a scrolling one

http://jsfiddle.net/wnHWH/1/

Bug: click on the scrollbar and drag it up or down to scroll through the content, when you release the mouse, the div starts to drag, which makes it follow your mouse around and there is no way to unstick it without refreshing the page.

dansch
  • 6,059
  • 4
  • 43
  • 59
  • 1
    A possible answer could be setting a title element that serves as the part you click to drag while keeping the scrollable content separate – dansch Nov 08 '12 at 16:28
  • I am trying to figure out the same problem. I have noticed that this behavior exists in Chrome. You can get the div to release from the mouse without refreshing by right-clicking and then clicking somewhere else. In Firefox, trying to scroll only succeeds in dragging the div, no scrolling happens, but it does not stick to the mouse when you release it. I haven't checked IE yet. – jonhopkins Nov 26 '12 at 17:23
  • I can't repo in Chrome or Safari on OS X 10.7. What browser/OS combos does this occur in? – evanmcdonnal Dec 01 '12 at 04:53
  • The fault occurs for me in Chrome 23.0.1271.95 m and IE 9. Both running on Windows 7. – Lee Taylor Dec 01 '12 at 13:00

3 Answers3

5

You can use .mousemove event of jquery like this:

$('#sortable div').mousemove(function(e) {
    width = $(this).width();
    limit = width - 20;
    if(e.offsetX < width && e.offsetX > limit)
        $('#sortable').sortable("disable");
    else
        $('#sortable').sortable("enable");
});

I have create fiddle that works here http://jsfiddle.net/aanred/FNzEF/. Hope it meets your need.

SubRed
  • 3,169
  • 1
  • 18
  • 17
  • This looks like it's close. However, if I add an outer DIV to the whole lot, with a padding of say 50px, the calculations are offset. Can this be fixed? – Lee Taylor Dec 01 '12 at 13:03
  • @LeeTaylor see my updated fiddle you need to change the `pageX` with `offsetX`. – SubRed Dec 01 '12 at 13:45
  • Many thanks. I'll have a look at testing this with my project later. Thanks for your time. – Lee Taylor Dec 01 '12 at 13:47
  • while I ended up just using a title element and setting the handle to be it(non scrollable), this works. – dansch Dec 12 '12 at 19:35
  • This isn't actually that good of a solution, because if you move your mouse out of the scrollbar's width while dragging, you'll trigger the sortable event and it will get stuck anyway. – Thomas Dignan Mar 10 '13 at 16:12
  • The other answer to use the 'handle: ' property is far more practical and accurate. – Thomas Dignan Mar 10 '13 at 16:18
4

sortable() can specify a selector for a handle much like draggable() does. Then only the matched elements get the click events. You specify the handle selector like this:

$('#sortable').sortable( {handle : '.handle'});

You already have most of what you need for the rest. The inner div on your overflowing element makes a suitable handle, like this:

<div style="height: 200px;overflow:auto">
    <div class="handle" style="height: 300;">
        blah
        blah
        blah

Then you need to restore the sortability of everything else. You'd think you could just give those divs the handle class, but it's looking for children, so you need to wrap all of them like so:

<div><div class="handle">asadf</div></div>

Modified fiddle

FoolishSeth
  • 3,953
  • 2
  • 19
  • 28
  • this answer is working perfect. it doesnt break if we click on the scroller – Rafee Dec 01 '12 at 14:08
  • This is the best answer. chosen answer is a hack and fails when you drag the mouse out of the scrollbar width boundary while scrolling. Sure, the hack prevents the issue if you keep the mouse within the width range of the scrollbar you specify, but users don't do that when they scroll. They move the mouse far to the left/right of the scrollbar quite often. – Thomas Dignan Mar 10 '13 at 16:18
3

Supplement to SubRed's answer:


This worked perfectly for my needs. However, rather than rely on the width of the scrollbar being 20 pixels (as above), I used the code from:

How can I get the browser's scrollbar sizes?

This allows the code to handle different scrollbar widths on different setups. The code is pasted here for convenience:

function getScrollBarWidth () 
{
    var inner = document.createElement('p');
    inner.style.width = "100%";
    inner.style.height = "200px";

    var outer = document.createElement('div');
    outer.style.position = "absolute";
    outer.style.top = "0px";
    outer.style.left = "0px";
    outer.style.visibility = "hidden";
    outer.style.width = "200px";
    outer.style.height = "150px";
    outer.style.overflow = "hidden";
    outer.appendChild (inner);

    document.body.appendChild (outer);
    var w1 = inner.offsetWidth;
    outer.style.overflow = 'scroll';
    var w2 = inner.offsetWidth;
    if (w1 == w2) w2 = outer.clientWidth;

    document.body.removeChild (outer);

    return (w1 - w2);
}

I've also used the width value for the height of the scrollbar and modified SubRed's code to suit. This now works with one or both scrollbars.

I also used code from:

Detecting presence of a scroll bar in a DIV using jQuery?

To determine the presence of either scroll bar and adapted the turning on/off of the sortable code accordingly.

Many thanks.

Community
  • 1
  • 1
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49