Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ability to scroll screen on drag #327

Open
dewyze opened this issue Mar 1, 2016 · 21 comments
Open

Allow ability to scroll screen on drag #327

dewyze opened this issue Mar 1, 2016 · 21 comments

Comments

@dewyze
Copy link

dewyze commented Mar 1, 2016

Currently, if dragging brings you to the edge of the viewport, the list will not scroll down. Ideally, it would be nice to have a feature similar to the one in jQuery UI. Source.

This can be tested simply on the dragula home page, put the page like this:
image

Grab an object and drag it to the bottom, the list will not scroll. This makes dragula unusable for long lists on smaller screens.

Thanks!

@bevacqua
Copy link
Owner

bevacqua commented Mar 1, 2016

Many have asked for this but in the end the PRs ended up falling through for one reason or another. #121 #129 #194 #200

I'd be thrilled if we could fix this :)

@aewens
Copy link

aewens commented Mar 6, 2016

For now, using up and down arrows / page up and page down buttons work while dragging elements. A decent fix would probably involve checking to see if the cursor + the element height is equal to the bottom of the visible portion of the page and then setting a setInterval loop to offset the scroll slightly every few milliseconds if that condition is still true. Once I get more familiar with the code base and have some free time I'll try to implement this.

@skitterm
Copy link

Investigating a few different drag-and-drop libraries, having scroll-drag would be a big win.

@xiwc
Copy link

xiwc commented May 9, 2016

i found if comment all the e.preventDefault(); it will can be scrolled when dragging.
image
image

@natzar
Copy link

natzar commented Jul 15, 2016

    drake.on('drag',function(el,source){                                    
        var h = $(window).height();                  
        $(document).mousemove(function(e) {     
            var mousePosition = e.pageY - $(window).scrollTop();
            var topRegion = 220;
            var bottomRegion = h - 220;
            if(e.which == 1 && (mousePosition < topRegion || mousePosition > bottomRegion)){    // e.wich = 1 => click down !                                                                                   
                var distance = e.clientY - h / 2;
                distance = distance * 0.1; // <- velocity
                $(document).scrollTop( distance + $(document).scrollTop()) ;                    
            }else{
                $(document).unbind('mousemove');
            }
        });
    });

@bevacqua
Copy link
Owner

@natzar Could you turn that into a PR? It'd need to bind your plugin as an option, and work for horizontal scrolling as well.

@natzar
Copy link

natzar commented Jul 18, 2016

Ok, redone in pure javascript. Travis doesn't let me finish PR. It says function scrollTo is defined but not used, really don't know what it expects, the function scrollTo is defined and used.

@akakoori
Copy link

@natzar sorry but have you tested this Jquery version in touch devices?

and $(document).scrollTop means it will scroll in the page not in dragula.container?
I think in most cases we want it to scroll in the dragula.container.
If I'm wrong, sorry.

@PhilLehmann
Copy link

As you can specify multiple dragula containers, thats also not optimal. Best would be a custom property like scrollContainer.

@akakoori
Copy link

akakoori commented Aug 17, 2016

finally find one way to make it scroll in the dragula.container on mobile.
Although there are so much things I am not sure, at least it works in my mobile...
I guess this might help someone, so I paste it at here:

      drake.on('drag',function(el,source){
        //you need to:
        //add a parent node as a mask of the dragula.container
        //and set its css with overflow:auto, max-height:somevalue
        mask = $(source).parent(); 
        var h = mask.height();
        mask.bind('touchend',function(e){
          mask.unbind('touchmove');
        });
        mask.bind('mousemove touchmove',function(e) { 
          var offset=mask.position().top;
          if(DRRR.isMobile){
            e.clientY = e.originalEvent.targetTouches[0].clientY;
          }
          var mousePosition = e.clientY - offset;
          //alert(mousePosition);
          var topRegion = 0.65 * h;
          var bottomRegion = 0.35 * h;
          if((DRRR.isMobile || e.which == 1) && (mousePosition < topRegion || mousePosition > bottomRegion)){    // e.which = 1 => click down !                                                                                   
            var distance = mousePosition - h / 2;
            distance = distance * 0.1; // <- velocity
            mask.scrollTop( distance + mask.scrollTop()) ;                    
          }else{
            mask.unbind('mousemove touchmove');
          }
        });
      });

@hollowdoor
Copy link

Back when a similar issue appeared I tried to fix this for dragula. I gave up because I couldn't figure out how to mix the functionality into dragula. So I made a separate library.

You nice people are welcome to take a look at my source if it helps you figure out how to implement something similar in the dragula source.

https://github.com/hollowdoor/dom_autoscroller/blob/master/src/index.js

Warning! I might not have figured it all out. There are cases I can't test for right now. Use it, or take inspiration from it to solve this problem in dragula.

@nguyenj
Copy link

nguyenj commented Dec 10, 2016

@dewyze I have a PR out for scrolling while dragging vertically and horizontally. Let me know if this works for you.

@LeaVerou
Copy link
Collaborator

I was just about to report this, glad I found the existing bug report before I did. This was my testcase, in case it helps: http://codepen.io/leaverou/pen/zogpWM

@silkgh
Copy link

silkgh commented Mar 27, 2019

I've tried every solution on this page & none work with nested containers. dom_autoscroller isn't an option as I'm not using nodejs. Completely stuck....

@jhon100
Copy link

jhon100 commented Apr 6, 2019

`$(document).mouseup(function(e){
$(document).unbind('mousemove');
});

drake.on('drag',function(el,source){
var mouseY;
var speed = 0.15;
var zone = 50;

$(document).mousemove(function(e){
   mouseY = e.pageY - $(window).scrollTop();
}).mouseover();

var dragInterval = setInterval(function(){

  if ($(el) && $(el).length > 0 && !$('html, body').is(':animated')) {
	var bottom = $(window).height() - zone;

  if (mouseY > bottom && ($(window).scrollTop() + $(window).height() < $(document).height() - zone)) {
	$('html, body').animate({scrollTop:  $(window).scrollTop() + ((mouseY + zone - $(window).height()) * speed)},0);
  }
  else if (mouseY < zone && $(window).scrollTop() > 0) {
	 $('html, body').animate({scrollTop: $(window).scrollTop() + ( (mouseY - zone) * speed) },0);

  } else {
	$('html, body').finish();
  }
  }
},16);

}`

This is working for me

@hughfuve
Copy link

hughfuve commented Jun 9, 2019

This jQuery code at least gives you mouseY and mouseX of the left corner of the element attached to your pointer.
var mouseY = parseFloat($(".gu-mirror").css("top"));
var mouseX = parseFloat($(".gu-mirror").css("left"));

I was not able to catch mousemove events to read e.pageY , but this gives you some coords to work with, and you can modify various solutions accordingly.

@hughfuve
Copy link

hughfuve commented Jun 9, 2019

Modified from jhon100's comment. because mouseover does not work for me.
USAGE:
Define a global object somewhere..
var yourGlobalObject = { };

Then include this code inside your drake.on("drag", function

yourGlobalObject.dragInterval = setInterval(function(){
    var zone   = 80;
    var speed  = 0.15;
    var mouseY = parseFloat($(".gu-mirror").css("top"));
    if ($(el) && $(el).length > 0 && !$('html, body').is(':animated')) {
        var bottom = $(window).height() - zone;
        if (mouseY > bottom && ($(window).scrollTop() + $(window).height() < $(document).height() - zone)) {
            $('html, body').animate({scrollTop:  $(window).scrollTop() + ((mouseY + zone - $(window).height()) * speed)},0);
        }
        else if (mouseY < zone && $(window).scrollTop() > 0) {
            $('html, body').animate({scrollTop: $(window).scrollTop() + ( (mouseY - zone) * speed) },0);

        } else {
            $('html, body').finish();
        }
    }
},20);

$(document).mouseup(function(e){                
    clearInterval(yourGlobalObject.dragInterval); 
});

Then inside your drake.on("drop", function add this to turn the scroll function off.
clearInterval(yourGlobalObject.dragInterval);
Because that mouseup event capture doesn't work for me either, but it might for you.

If you are worried about using too much CPU, you can try increasing the ,20); interval to 100+. The scrolling will become less smooth. a value of 16 will attempt to run at 60fps.

Note, this solution assumes you want to scroll something inside the whole visible window.

@nikku
Copy link

nikku commented Jul 8, 2019

Scrolling of screen / underlying scroll containers can be easily accomplished by the following:

.gu-mirror {
  pointer-events: none;
}

Otherwise the .gu-mirror instance consumes scroll events, preventing scrolling of the visually underlying scroll container.

@dnizetic
Copy link

dnizetic commented Feb 10, 2020

Scrolling of screen / underlying scroll containers can be easily accomplished by the following:

.gu-mirror {
  pointer-events: none;
}

Otherwise the .gu-mirror instance consumes scroll events, preventing scrolling of the visually underlying scroll container.

You sir, are a genius. I've no idea why this is not upvoted. I could not figure out why mouse wheel would not work inside the scrolled container.

Adding this single piece of CSS worked like a charm.

@ThalyssonLeite
Copy link

Scrolling of screen / underlying scroll containers can be easily accomplished by the following:

.gu-mirror {
  pointer-events: none;
}

Otherwise the .gu-mirror instance consumes scroll events, preventing scrolling of the visually underlying scroll container.

I have the same problem but I'm not using that library, and I cannot find the problem... could you help me? I have the container wich will handle the scroll, I have the box to be scrolled and the img that you be used to trigger the scroll action... whose should I put pointer-events: none? I've tried everything and I just can't make it work.

@ThalyssonLeite
Copy link

Scrolling of screen / underlying scroll containers can be easily accomplished by the following:

.gu-mirror {
  pointer-events: none;
}

Otherwise the .gu-mirror instance consumes scroll events, preventing scrolling of the visually underlying scroll container.

You sir, are a genius. I've no idea why this is not upvoted. I could not figure out why mouse wheel would not work inside the scrolled container.

Adding this single piece of CSS worked like a charm.

I have the same problem but I'm not using that library, and I cannot find the problem... could you help me? I have the container wich will handle the scroll, I have the box to be scrolled and the img that you be used to trigger the scroll action... whose should I put pointer-events: none? I've tried everything and I just can't make it work.

I'm writting again because this is a very outdated issue... could you help me?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests