简体   繁体   中英

Scrolling a Div from Anywhere

When the bottom of my page (aka #main ) comes into view jQuery toggles a class on my sidebar to make it scrollable using overflow-y: scroll — and overflow: hidden when the bottom of the page is out of view.

The desired effect here is to be at the bottom of the page (again in my example that's the #main div) , but allow for the sidebar to keep scrolling provided there's more content.

So if you were to keep scrolling down on #main even after you'd reached the bottom, the sidebar would begin to scroll.

The problem right now is the desired scrolling effect only works when the cursor's over #sidebar . I'd like for it to be more natural andcapable of scrolling without the cursor needing to be over the #sidebar .

HTML :

<div id="container">
    <div id="header"></div>

    <div id="main"> 
        <p>Lorem ipsum dolor sit amet, [...]</p>   
    </div>
    <div id="sidebar">
        <ul>
            <li>Item 1</li>
            <li>Item 2</li>
            <li>Item 3</li>
            <li>Item 4</li>
            <li>Item 5</li>
            <li>Item 6</li>
            <li>Item 7</li>
            <li>Item 8</li>
            <li>Item 9</li>
            <li>Item 10</li>
            [...]
         </ul>
    </div>
</div>

Javascript :

$('#sidebar').height( $('#main').height() );

$('#main').waypoint(function() {
    $('#sidebar').toggleClass('scrollable');
}, { offset: 'bottom-in-view' });

I've setup a fiddle for my question here: http://jsfiddle.net/ZZqLr/


Follow-Up: By approaching the problem from another angle I managed to achieve the desired effect.

This time around, when the bottom of #main comes into view it becomes fixed to the bottom of the window, while the #sidebar continues to scroll freely. It's a bit of a hack, but is visually identical for my needs.

http://jsfiddle.net/ZZqLr/1/

You can catch the scroll event of a mouse with the following code:

var mouseWheelEvent = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel"; //FF doesn't recognize mousewheel as of FF3.x

if (document.attachEvent) { //if IE (and Opera depending on user setting) 
    document.attachEvent("on"+mouseWheelEvent, mouseWheelEventHandler);
} else if (document.addEventListener) { //WC3 browsers 
    document.addEventListener(mouseWheelEvent, mouseWheelEventHandler, false);
}

After this it is quite easy to see when someone scrolls, even though you have reached the end of the document. The mouseWheelEventHandler is the function that I passed to handle your mouseWheelEvent for you, it looks like this:

function mouseWheelEventHandler(e)
{
    if( !sidebar.hasClass('scrollable') && !sidebar.is(":hover") ) {
        return true;
    }

    var event = window.event || e; //equalize event object
    var delta = event.detail ? event.detail*(-120) : event.wheelDelta; //check for detail first so Opera uses that instead of wheelDelta
    sidebar.scrollTop(sidebar.scrollTop()-delta);        
}

It will only scroll the sidebar if the sidebar has the class scrollable and if you are not already with your mouse on the sidebar, as it would scroll that element anyway and you would and up double scrolling it.

This should work on most browsers according to the following link: http://www.javascriptkit.com/javatutors/onmousewheel.shtml

And here is the fiddle to play with ofcourse: http://jsfiddle.net/ZZqLr/5/

EDIT

To complete the answer, we'll add the behaviour of it only scrolling the sidebar up instead of the page when you scroll up again, for this we only have to prevent the scrolling event by event.preventDefault() and add the following code at the end of the mouseWheelEventHandler :

if( sidebar.scrollTop() == 0 ) {
    sidebar.removeClass('scrollable');
}

the function then looks like this:

function mouseWheelEventHandler(e)
{
    if( !sidebar.hasClass('scrollable') && !sidebar.is(":hover") ) {
        return true;
    }
    var event = window.event || e; //equalize event object
    event.preventDefault();
    var delta = event.detail ? event.detail*(-120) : event.wheelDelta; //check for detail first so Opera uses that instead of wheelDelta
    sidebar.scrollTop(sidebar.scrollTop()-delta);
    if( sidebar.scrollTop() == 0 ) {
        sidebar.removeClass('scrollable');
    }
}

Again you can play with it right here: http://jsfiddle.net/ZZqLr/6/

By the way, the waypoints.js is not even necessary for this, just for fun, one without the waypoints.js by removing the waypoint function and just adding the following in the eventHandle function:

function mouseWheelEventHandler(e)
{
    if( !sidebar.hasClass('scrollable') && !sidebar.is(":hover") ) {
        if($(window).scrollTop() + $(window).height() == $(document).height()) {
            sidebar.addClass('scrollable');
        }
        return true;
    }

    var event = window.event || e; //equalize event object
    event.preventDefault();
    var delta = event.detail ? event.detail*(-120) : event.wheelDelta; //check for detail first so Opera uses that instead of wheelDelta
    sidebar.scrollTop(sidebar.scrollTop()-delta);
    if( sidebar.scrollTop() == 0 ) {
        sidebar.removeClass('scrollable');
    }
    return true;
}

And for playing with that as well, you might've guessed: http://jsfiddle.net/ZZqLr/7/

And that will be all, I guess :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM