I'm considering adding drag and drop functionality to my Webforms application.
One consideration is that the drag source and drop target may be far enough away from each other to require scrolling. So I thought a cool UI would be for an overlay to appear at the top and bottom of the browser window when the user starts to drag.
This overlay would be a shaded area with an arrow (the top overlay would have an Up arrow and the bottom overlay would have a Down arrow). When the user drags over the overlay, the window would scroll in that direction.
Questions:
Does anyone have any experience with anything like this? Do you know if it can be done reliably across browsers?
Can anyone recommend a jQuery plugin that could do the heavy lifting?
Any other thoughts or recommendations?
I got also some issues with that functionality. I solved it by styling my draggable element with margin: 0 and padding: 0 and make it consistent with a width and a height properties.
More I used margin and padding properties on draggable, sortable and droppable elements more I had issues.
Hope it will help you !
Related
High level: What kind of things can prevent the mouse wheel from being interpreted properly for scrolling? What are some debugging tools to check these?
I have a section of my page that is correctly displaying a vertical scroll bar. However the scroll wheel on the mouse fails to scroll the section unless the mouse is directly over the scroll bar.
What I believe is the relevant div has overflow-x: hidden and overflow-y: auto.
These are coming from the Zurb Foundation Apps CSS. I have, unfortunately, been unable to replicate this behavior within jsfiddle, so I'm hoping for further investigative tips.
This appears to relate to Foundation Apps grid-block classes. If you have a grid-block which has a single child grid-block this can somehow prevent the scroll wheel working.
I ended up replacing the child grid-block with a raw, full-width div.
I found the problem was the grid-frame class, specifically setting the height as 100vh causes the scroll wheel to bug out.
I replaced the grid-frame with a grid-block and didn't use grid-frame at all.
In HTML/CSS/JS, there is one thing I am having trouble figuring out:
How to prevent people from scrolling an element using the mouse wheel press (i.e. hold down the mouse wheel and drag, or click the mousewheel, drag, click the mouse wheel again) and how to do the same when people try to drag the elements around on a touch-device.
This is something I stumble upon, amongst other places, when trying to make a hamburger-style menu.
Setting an element's CSS to overflow: hidden will hide the scroll bars, but using above two methods, it is still easy to scroll through them.
Until now, the only 'solution' I found was to make a second element, and position it on top of the element that should not be scrollable. But this hardly seems like a perfect solution to me.
How can these events be captured using JavaScript?
How can, on, for instance, this page, scrolling horizontally and vertically be blocked when the menu is open?
If you create a jsfiddle, we can give a better solution. If you are OK with jquery, I can give some solution for your second point "How can, on, for instance, this page, scrolling horizontally and vertically be blocked when the menu is open?".
First you need to create one simple class like below.
.overhidden
{
overflow:hidden !important;
}
Next, we need to apply this class when you press the menu icon on your screen. Also we need to remove if they click again for closing. It is easy to do in jquery like below.
$(document).ready(function(){
$('#hamburger').click(function(){
$('body').toggleClass('overhidden');
});
});
What I'm trying to do is have a block(let's call it .top) that is fixed and another block(let's call this one .content), that, when scrolling, goes over .top, this all while retaining everything that .top contains clickable.
Now there are some obvious setups
this
http://jsbin.com/rucifuzu/1/edit?html,css,output
or this
http://jsbin.com/hufomaxu/1/edit?html,css,output
problem with both is a) you have to account for scrollbar width b) scrolling/swiping on .top won't do anything with the element with overflow: auto underneath it
I have thought about a couple of solutions.
First would be pointer-events: none on .top, which would make it "transparent" for mouse events, thus triggering scroll on whavever is under it, the problem with is that click events won't work either, and since I plan on having clickable and selectable thing inside .top, it's a problem. I could reset pointer-events back to auto just for those click/selectable thing, but considering one of those clickable things is gonna be big ass headline, I'm gonna have a problem with scroll not working with mouse position on it again.
Second was what I call scroll delegation, using JS I would catch mousewheel events and change scrollTop on the overflow: auto element. This would work fine, except that it might result in different scroll "feel" while this delegation is happening and while native scroll on .content kicks in. It's also pain in the arse to get this behaving correctly on touch devices.
So neither is ideal. Have I missed any genious and simple solution to this problem?
TL;DR Goal is to have the .top element BOTH clickable and "scroll-thru-able"
this way .top is clickable, but element under it won't scroll - http://jsbin.com/hufomaxu/1/edit?output
this way element under it will scroll, but .top is not clickable - http://jsbin.com/tuluwili/1/edit?output
Not sure I understand 100% - you want to visually cover up a fixed element while scrolling but still be able to click on it?
One simple solution might be using 3 layers instead of 2.
Bottom layer contains your links and is fixed.
Middle layer is the one that will scroll over it and cover it up.
Top layer is fixed and is identical to Bottom layer except clear all the background colors and set opacity to 0.
When you scroll it would look like the bottom is being covered up but you could still click on the top invisible layer.
Might not work if you need to do things like drag to copy text or interact in other ways with the middle layer.
I have an overflow: hidden div which I am scrolling by allowing the user to click and drag the background. There are also links and buttons in this space.
This is what I do for the CSS:
#div-grabscroll {
cursor: url(../img/openhand.cur), move;
}
#div-grabscroll:active {
cursor: url(../img/closedhand.cur), n-resize;
}
This works great but what happens is that while dragging, if the mouse ends up moving (due to reaching scroll limits) over a button the pointer cursor overrides my closedhand cursor.
The desired behavior is that for the entire duration that the div is being controlled by the mouse, I want the cursor to remain the closedhand.
Is there a way to override the cursor without modifying CSS for everything that the mouse might move over? I tried !important on the :active style but that didn't do it.
Answer / Question: What would happen if you had a duplicate div which sat on top of the grabscroll div, but which had no background or content of any type so as to not hide anything behind it, and then set the cursor hand on this.
Does z-index overwrite importance this way?
Does this make sense?
Effectively you have grabscroll - button - opaque grabscroll in that layered order.
This is a very similar problem to creating "modal" dialog boxes, and it will probably have a similar solution: I think you'll have to create an iframe positioned over the content you're scrolling, making it higher up in the z-index order than the content, for the duration of the scroll. This is because on IE (at least) form controls tend not to obey z-index well, which is why "lightbox"-style things do this iframe shim thing.
Here's an answer I gave to another question here on SO which demonstrates the basics of the iframe shim. In that case it's for modal purposes, but the concept and most of the code would apply.
I got a html page with a sliding panel on the right. This panel is 200px wide, position: fixed, and its position is initially set to right: -100px (halfway outside of the clientArea). Overflow-x is set to hidden for body, html (css), and the panel accepts mouseover events and drop events. On mouse over, the panel slides to right: 0.
If I drag a draggable element on this panel, the panel correctly slides to left, but the window starts to scroll to right, which is an unwanted behaviour.
I also tried a javascript solution as described here: Disable horizontal scroll with JavaScript
but is's a bad workaround because it make the clientArea start flickering.
What is the best way to completely disable horizontal scrolling? Possibly a cross browser solution.
Thanks
Update:
It's not the sliding panel causing the issue, but the helper object of the draggable element (I'm using jquery-ui), which is anchored to the mouse position at top left while dragging. Imagine the helper object as a div 200x100px. When dragged to the rightmost part of the window area, the issue shows up scrolling the window to the right, instead of clipping the helper (and not scroll the window). I sort of manage this by anchoring the mouse to the top right corner of the helper during the drag operation, but I'm still curious if there is any way to completely disable the horizontal scroll of the window. I supposed the helper object to be completely "detached" from the page flow (as happens using position: absolute in css), but apparently it's not.
I ended up changing my initial requirements and thus the page design.
And what if you do not place the panel at right: -100px, but give it a width of 100px and place it at right: 0px?
Then on mouseover animate the width to 200px. It still feels like a slide. I don't know if the content of your panel allows the change of the width, but maybe you can give the panel an overflow: hidden too.