Search code examples
javascriptjqueryjscrollpanehighlightingjquery-jscrollpane

jScrollPane scrolling on element drag


I am trying to scroll by highlighting text and dragging down. Now, as you are probably aware, this is standard, default behavior for a standard overflow: auto element, however I am trying to do it with some fancy scrollbars courtesy of jQuery jScrollPane by Kelvin Luck.

I have created a fiddle here: DEMO

basically as you can see, highlighting and scrolling works in the top box (the default overflow: auto box) but in the second it doesn't and, to compound matters, once you reach the bottom it INVERTS your selection!

So, my question(s) is(are) this(these): is there a way to fix this? If so, how?

UPDATE

I have been working on this quite a bit and have found a slight solution using setTimeout()

however, it doesn't work as intended and if anybody is willing to help I have forked it to a new fiddle here: jsFiddle

the code itself is:

pane = $('#scrolldiv2');
pane.jScrollPane({animateEase: 'linear'});
api = pane.data('jsp');

$('#scrolldiv2').on('mousedown', function() {
    $(this).off().on('mousemove', function(e) {
        rel = $(this).relativePosition();
        py = e.pageY - rel.y;
        $t = $(this);
        if (py >= $(this).height() - 20) {
            scroll = setTimeout(scrollBy, 400, 20);
        }
        else if (py < 20) {
            scroll = setTimeout(scrollBy, 400, -20);
        }
        else {
            clearTimeout(scroll);
        }
    })
}).on('mouseup', function() {
    $(this).off('mousemove');
    clearTimeout(scroll);
})

var scrollBy = function(v) {
    if (api.getContentPositionY < 20 & v == -20) {
        api.scrollByY(v + api.getContentPositionY);
        clearTimeout(scroll);
    } else if (((api.getContentHeight - $t.height()) - api.getContentPositionY) < 20 & v == 20) {
        api.scrollByY((api.getContentHeight - $t.height()) - api.getContentPositionY);
        clearTimeout(scroll);
    } else {
        api.scrollByY(v, true)
        scroll = setTimeout(scrollBy, 400, v)
    }
}

$.fn.extend({
    relativePosition: function() {
        var t = this.get(0),
            x, y;
        if (t.offsetParent) {
            x = t.offsetLeft;
            y = t.offsetTop;
            while ((t = t.offsetParent)) {
                x += t.offsetLeft;
                y += t.offsetTop;
            }
        }
        return {
            x: x,
            y: y
        }
    },
})​

Solution

  • You just have to scroll down/up depending on how close the mouse is to the end of the div; is not as good as the native solution but it gets the job done ( http://jsfiddle.net/PWYpu/25/ )

    $('#scrolldiv2').jScrollPane();
    
    var topScroll = $('#scrolldiv2').offset().top,
        endScroll = topScroll + $('#scrolldiv2').height(),
        f = ($('#scrolldiv2').height() / $('#scrolldiv2 .jspPane').height())*5 ,
        selection = false,
        _prevY;
    
    $(document).mousemove(function(e){
        var mY;
        var delta = _prevY - e.pageY;
        if((e.pageY < endScroll && (mY = ((e.pageY - endScroll + 80)/f)) > 0) || 
           (e.pageY > topScroll && (mY = (e.pageY - (topScroll + 80))/f) < 0)){
              if(selection && (delta > 10 || delta < -10) )
              $('#scrolldiv2').data('jsp').scrollByY(mY, false) ;
        } 
    })   
    
    $('#scrolldiv2').mousedown(function(e){_prevY = e.pageY; selection = true ;})
    $(window).mouseup(function(){selection = false ;})​
    

    BTW, the reason it inverts the selection is because it reached the end of the document, just put some white space down there and problem solved.