views:

617

answers:

5

Here is my current situation:

I have a web page containing a couple scrollable divs. Each of those divs contains a number of objects. I am using YUI to display popup menus of actions that can be performed on each object. Each object has its own menu associated with it that is constructed and displayed dynamically. The popup menus can be large and can overlap the bounds of the scrollable div.

From what I believe are issues with focus (the menus must be accessible), when I hover the mouse over an action that lies on top of an edge of the scrollable div, the div automatically scrolls, moving the content but leaving the menu stationary. Trying to move the menu dynamically when this happens is not something I want to do as I believe it would provide a poor user experience.

So I need to prevent this focussed menu from scrolling the div. My idea for providing the best user interface is to prevent these inner divs from scrolling when a menu is open. This leaves the menu positioned in the optimal location to show the user which item is being acted upon. If the user wants to scroll the box, they can click to close the menu and then scroll normally.

How can I do this? I need a solution that works across the major browsers.

My first thought was to listen to the onscroll event for that particular element. Unfortunately, there does not seem to be an easy way from there to just prevent the scrolling from happening. For one, my Javascript event code appears to execute after the actual scrolling has occurred.

Then, I thought that since my code is being run after the object has scrolled, I could just reset obj.scrollTop and obj.scrollLeft. Sure enough, this appears to work, though I am worried that on slow browsers the user will see the content inside the div "jump around". Also, it would be really nice if the amount the element scrolls is part of the event object. Is it stuck in there somewhere? I'm looking for an alternative to having to store the scrollTop and scrollLeft variables for this element and then using them while the scrolling is temporarily disabled.

What is the best way to solve this entire problem?

+3  A: 

The simple answer is no you can't do this. Its doubly no if you want a cross-browser solution.

Providing the user with the clear affordance that something can be scrolled then denying them that is just plain poor UI design.

Ok so after your edit it turns out you are not actually trying to prevent the user from scrolling.

The main answer remains true though. It sounds as though the focus is going to rectangle (probably an anchor?) that is not fully in view and causes a scroll. Is there a reason this rectangle must get the focus? For accessibility?

AnthonyWJones
I have updated the question to better describe what I am trying to accomplish. I currently think the user interface is very usable and very well designed. But the fact that the menu's focus causes the underlying div to scroll is horrible and I need a way to work around it.
Sebastian Celis
Yes, the menu is a list of anchor tags which needs to gain focus for accessibility concerns. Then menu is fully in view, but the act of moving the mouse near the edge of the scrollable div causes the browser to think it should scroll it for me.
Sebastian Celis
A: 

What if you didn't have overflow: scroll and instead you used overflow: hidden and provided scroll up/down buttons that allowed the user to scroll when necessary? These buttons could of course be disabled easily.

Eric Wendelin
Objects with an overflow of hidden will still scroll in my situation. Try creating a div with an overflow of hidden that is sized to be small but contains a lot of text. You can stills scroll that box with the mousewheel or by clicking and dragging when selecting the text.
Sebastian Celis
You'd have to preventDefault() of the onscroll event etc. I suppose :)
Eric Wendelin
Yep, I tried that. Doesn't work. Thanks, though.
Sebastian Celis
A: 

Though it may not be the answer you are looking for, if you are to set the display value of the div to 'none' while the page loads (from the server) and then have an event wired to the page load (either pageLoad in ajax.net or attach it to the onload event via javascript) that will make the div display set to 'block' .. that would ensure that slower browsers wouldn't see the div 'jumping around' (could even put a 'loading' image in the div to show users it's doing something and not just invisible)

sorry i couldn't provide a more complex/fluent solution.

John West
+2  A: 

I agree with Anthony regarding the presentation of the functionality you're trying to disallow. If you're going to disable scrolling, then you should make that part of the page visually disabled or removed.

To that end, you can position a semi-transparent div on top of the scrollable div in question, which would capture the mouse events and visually show that the scrollable div is inactive for now. It would be hard to make cross-browser compatible and wouldn't be perfect, but then again very few client-side tricks like this are.

Welbog
A: 

I found a way to work around this issue. By removing the menu element from the scrollable div and then appending it directly to document.body, the browsers all stop trying to scroll the div to reveal the focused element (even though the element is already completely visible).

Thanks to all for your time and your answers!

Sebastian Celis