dragula
dragula copied to clipboard
Best way to prevent page scrolling on drag (mobile)
Whenever I drag on a long page the whole page moves along with the scroll. On mobile and tablet this can be annoying and a bit unusable. Does anyone have a good suggestion for nixing the scroll while drag?
Any idea?
You could make the page non-scalable and non-scrollable for mobile browsers,
something like this in the HEAD section:
<META name="viewport" content="initial-scale=0.66, user-scalable=no">
You can also disable android/chrome browser from refreshing when you drag downward by changing this setting on the browser itself:
chrome://flags/#disable-pull-to-refresh-effect
Of course these aren't fixes, but they may buy you some time until you find a fix.
This worked for me - I hope it helps someone else:
drake = dragula({
revertOnSpill: true,
mirrorContainer: document.querySelector('.movecontainer')
}).on('drag', function(el, source) {
// On mobile this prevents the default page scrolling while dragging an item.
$(document).on('touchstart', function(e) {
e.preventDefault();
});
}).on('drop', function(el, target, source, sibling) {
// On mobile this turns on default page scrolling after the end of a drag drop.
$(document).off('touchstart');
});
It requires jQuery of course.
Hello
I'm not sure this is the correct place to ask this, so feel free to move my comment if it is not.
I have the same issue, however I do not want to simply disable the scrolling while dragging, I want to be able to make the page scroll down by dragging an item to the bottom, like the Google Drive app does when moving files. That way, I would be able to put an item from the very top of the list to the bottom in one drag, as opposed to multiple drags right now.
Is it possible by modifying the solution given here or is there any other way?
@AlbaVenzal I'll start working on this. @bevacqua could you assign me this issue?
Meanwhile this solution simple solution/hack works Flickity issue 457 comment
window.addEventListener( 'touchmove', function() {})
But since this disables scrolling totally, you're not able to make the page scroll down by dragging an item to the bottom.
@andresarpi / @bevacqua have you resolved this issue? Thanks!!!
Hello guys, what about this issue?
hey @snobojohan the solution window.addEventListener( 'touchmove', function() {}) dont work for me on iphone with ios 11. do you know what am i doing wrong? Thanks
@yosigolan please try
document.addEventListener('touchmove', function() { e.preventDefault(); }, { passive:false });
@Somethingideally based on your solution, I came up with (to avoid completely preventing scrolling on the page):
dragula([dndContainer], {
direction: 'horizontal'
})
.on('drop', function(element, targetContainer, sourceContainer, sibling){
$(document).off('touchmove');
})
.on('drag', function(el, source) {
$(document).on('touchmove', function(e) { e.preventDefault(); }, { passive:false });
});
It improved things on iOS: the horizontal scrolling issue is gone, but we still have vertical scrolling issues. Any idea what the problem might be?
Hello, @Jenselme, you can try this solution:
var scrollable = true;
var listener = function(e) {
if (! scrollable) {
e.preventDefault();
}
}
document.addEventListener('touchmove', listener, { passive:false });
dragula([dndContainer], {
direction: 'horizontal'
}).on('drag', function(el, source) {
scrollable = false;
}).on('drop', function(el, source) {
scrollable = true;
});
@Somethingideally still broken :-(
Hey @Somethingideally Thank you! it solved it! i do it a little differently to destroy the event subscription when the component is destroyed: @HostListener('touchmove', ['$event']) private onTouchMoveEvent(event:Event): void { event.preventDefault(); }
do you know in any chance how to solve this as well: https://github.com/valor-software/ng2-dragula/issues/517 (this is an issue on android only)
Thanks Yosi
Somethingideally's solution worked immediately for my Dragula-enabled page. Thanks very much for your well thought out and helpful code. Oddly, this only began to happen a couple of days ago. When I run an earlier, formerly-working version on Android now, it breaks.
@Somethingideally shouldn't this be using dragend
to reset scrollable
? Otherwise scrolling is not re-enabled after a cancel or removal, only after a successful drop.
@chrisdeeming, yes, later im added this
dragula([dndContainer], {
direction: 'horizontal'
}).on('drag', function(el, source) {
scrollable = false;
}).on('drop', function(el, source) {
scrollable = true;
}).on('dragend', function(el, source) {
scrollable = true;
// your logic on dragend
});
I think only this is needed:
dragula([dndContainer], {
direction: 'horizontal'
}).on('drag', function(el, source) {
scrollable = false;
}).on('dragend', function(el, source) {
scrollable = true;
// your logic on dragend
});
Hey guys, I wonder nobody found a solution yet. Just prevent the default touchmove
events on the container
, so it does not bubble up to the window.
const container = document.querySelector(...);
const dragula = window.dragula(
[
container
]);
/* handle scroll */
container.addEventListener('touchmove', event => event.preventDefault());
Works for me... :-)
@redaxmedia this prevents scrolling the container entirely though.
@rohan-deshpande Nope, it prevents the window to scoll while dragging elements inside the container. It is not perfect but should work for most user interfaces. Feel free to contribute a better solution.
What mobile browsers are you testing on and what version of the operating system? Can you post a fiddle or codepen as an example? I’ve tried this out and it’s prevented scrolling completely in iOS >= 11.3. No need to be defensive mate I’d be very happy if this worked but it hasn’t worked for me so I’m just wondering what exactly is going on.
Unfortunately, I did not test it on iOS as lack of devices. It works on Desktop Chrome (with sensor / responsive view) and Mobile Chrome on Android 6 like shown in the GIF.
No time to create a fiddle at this moment, but you can login to the Redaxscript Demo and browse the Admin Listing to play around with it.
Thanks for the explanation and gif. I can’t see anything on that page sadly, I’m assuming it’s behind some authentication?
Please click the first link - it does some kind of auto-login
Thanks for that, this does seem to be working, it’s a bit janky but yeah it works! I’m curious as to how you are handling scrolling while dragging while preventing the default event. Are you scrolling the page with JavaScript at any point?
this prevents scrolling the container entirely though.
Unfortunately, you were right with this statement. I did not realize this, yet.
Finally, I found a solution that allows scrolling over the container but disables scrolling the window while dragging some element inside the container.
- Use a drag handle
moves: (element, container, handle) =>
{
return handle.classList.contains('drag-handle-class');
}
- Prevent the default event on the drag handle
const moveList = document.querySelectorAll('div.drag-handle-class');
if (moveList)
{
moveList.forEach(move =>
{
move.addEventListener('touchmove', event => event.preventDefault());
});
}
Interesting, thanks for this. I spent a chunk of time attempting to migrate to react-beautiful-dnd only to discover that nested scroll containers are not supported. Even though that library is very nice the lack of that support breaks my interface so I’ll try this out and see if it works.
@rohan-deshpande Hopefully, you can get it working... give the drag handle approach a chance :-)
@redaxmedia this works for my implementation. Thanks very much!