Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Expanding a collapsible set should scroll you to the top of it's contents #2167

Closed
InvisibleBacon opened this Issue · 24 comments
@InvisibleBacon

If you have more than a page's height worth of contents in your first collapsible container, and you scroll down to the second set to expand, the browser's scroll position does not change, leaving you in the middle of the second container's contents. I fixed this on our site by scrolling to the top of the clicked header if it is off the top of the page after an expansion. Here's the code I use:

$("div.ui-collapsible-set").live("expand", function(e) {
    var top = $(e.target).offset().top;
        if ($(window).scrollTop() > top)
            $(window).scrollTop(top);
});
@LockyBoy

Really useful bit of code, thanks for that

@toddparker

This seems like a good idea. Mind creating a pull request?

@johnbender johnbender was assigned
@ricksuggs

Cover the case that there is a previously expanded collapsible whose collapsing will cause the position of the subsequently expanding collapsible to change before adjusting the scroll position:

var lastExpanded;
$('div.ui-collapsible-contain').live('expand', function() {
    var $expandable = $(this);
    // wait until the lastExpanded is collapsed
    var intervalId = setInterval(function() {
        if (lastExpanded && lastExpanded.has( ".ui-collapsible-heading-collapsed" )) {
            var expandableTop = $expandable.offset().top,
            $window = $(window),
            targetPos = expandableTop - $window.scrollTop() + $expandable.height();
            if (targetPos > $window.height() || expandableTop < $window.scrollTop()) {
                $.mobile.silentScroll(expandableTop);
            }
            clearInterval(intervalId);
            lastExpanded = $expandable;
        } else {
            lastExpanded = $expandable;
        }
    }, 200);
});
@CaDs

You just made my day!
Thanks a lot for the code

@adrianpillinger

The current version of jquery-mobile (1.0) needs a slightly different class in the initial selector.

        var lastExpanded;
        $('div.ui-collapsible').live('expand', function() {
            var $expandable = $(this);
            // wait until the lastExpanded is collapsed
            var intervalId = setInterval(function() {
                if (lastExpanded && lastExpanded.has( ".ui-collapsible-heading-collapsed" )) {
                    var expandableTop = $expandable.offset().top,
                    $window = $(window),
                    targetPos = expandableTop - $window.scrollTop() + $expandable.height();
                    if (targetPos > $window.height() || expandableTop < $window.scrollTop()) {
                        $.mobile.silentScroll(expandableTop);
                    }
                    clearInterval(intervalId);
                    lastExpanded = $expandable;
                } else {
                    lastExpanded = $expandable;
                }
            }, 200);
        });

Has this code been added to jQuery mobile, or do you want a pull request still ?

@toddparker

We did a bit of work on this but ran into some issues on edge cases. If this is working well for you and works on our target browsers, I'd love to see a pull request, sure.

@adrianpillinger

I've not done any extensive testing yet with this, but would be happy to test it and attempt to tweak to work with the browsers I have access to...

iOS 5
Android (not sure what version off hand)
Current latest version of
Safari on Mac OS X
Firefox on Mac OS X
Firefox on windows
Chrome on windows
Chrome on Mac OS X

I'll have a play and if I get something working with the browsers I have access to I'll issue a pull request for someone to complete testing on other browsers.

Cheers
Adrian

@toddparker

@adrianpillinger - We can test this on our side too. Do you have a demo page or PR?

@adrianpillinger

Sorry for the slow reply - busy at work and home...I am working on a pull request.

@adrianpillinger adrianpillinger referenced this issue from a commit in adrianpillinger/jquery-mobile
@adrianpillinger adrianpillinger #2167 Implementing auto-scroll to top of collapsible sections on expand.
Adds an event listener to enable auto scroll to the top of a
collapsible section when it is expanded. Credit is due to @ricksuggs
for the implementation of the scroll code.
2b7eec4
@adrianpillinger

Pull request made.

@sblenkhorne

That's perfect! Thanks so much for sharing this. So easy to use. Copy and pasted in my code it worked without a hitch. That rarely happens!
Thanks!

@jaspermdegroot
Collaborator

Link to the PR for this feature: #3520
This PR was closed, not merged, because there was too much jumpiness.

@toddparker

Closing as a feature request, but we'll give this another look for a later release.

@toddparker toddparker closed this
@jostster

@toddparker http://m.box.com does this very smoothly. Can you work with them to see how they achieved this?

@dmcaodha

Thanks for the code, great job.

@jaspermdegroot
Collaborator

I removed the feature request label and milestone 1.4 from this ticket. We will use #5394 as ticket for this feature now we are looking into the solution offered there.

@mtigue

Wow, worked like a charm. Thanks so much.

@frankygalore

That's f*ckin' amazing! Thank you so much! You guys made my day!

@mzestars

I'm still new with jquery. How do i add this to my page?

@mzestars

thanks :+1:

@reyandersen

Thanks a bunch.
For my own use I changed it slightly, so that it only scrolls if the top of the expanding collapsible is not visible

if (expandableTop < $window.scrollTop())

@bpnyc

Hi,
Thank you very much for the code. It was working great but I upgraded to jquery.mobile-1.3.2 and the .live function is no longer supported, so I've updated it to use .on

$(document).on("expand", 'div.ui-collapsible-set', function(e) {
var top = $(e.target).offset().top;
if ($(window).scrollTop() > top)
$(window).scrollTop(top);
});

@fjbotto

Hi, all, i had made my function to get this done, because none of those functions worked for me.
So my code, if it helps to anyone here it is:

var that = "";
function binEventHandlers(){
$( "a.ui-collapsible-heading-toggle" ).on("click", fncClick);
}
function fncClick(){
that = $(this);
var timeoutId = setTimeout(function(){fncAnimate()},100);
}
function fncAnimate(){
$('html, body').animate({scrollTop: that.offset().top});
}
$(document).bind("pageinit", function(event, ui) {
binEventHandlers();

});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.