Smart repositioning of opened collapsibles (with code) #5394

Closed
pillex opened this Issue Dec 20, 2012 · 12 comments

Projects

None yet

7 participants

@pillex
pillex commented Dec 20, 2012

//
// scroll an element fully into view
//
// if fully visible: do nothing
// if partly visible: scroll as little as to make it fully visible
// if larger than viewport: scroll to top of screen
//
// after expanding or loading an element it's often badly positioned and you 
// start scrolling immediately. this scrolls it into the best possible position
//
//
// demo: http://jsbin.com/udahoh/4/
//


function smart_scroll(el, offset) 
{ 


offset = offset || 0; // manual correction, if other elem (eg. a header above) should also be visible

var air         = 15; // above+below space so element is not tucked to the screen edge

var el_height   = $(el).height()+ 2 * air + offset;
var el_pos      = $(el).offset();
var el_pos_top  = el_pos.top - air - offset;

var vport_height = $(window).height();
var win_top      = $(window).scrollTop();

//  alert("el_pos_top:"+el_pos_top+"  el_height:"+el_height+"win_top:"+win_top+"  vport_height:"+vport_height);

var hidden = (el_pos_top + el_height) - (win_top + vport_height);

if ( hidden > 0 ) // element not fully visible
    {
    var scroll;

    if(el_height > vport_height) scroll = el_pos_top;       // larger than viewport - scroll to top
    else                         scroll = win_top + hidden; // smaller than vieport - scroll minimally but fully into view

    $('html, body').animate({ scrollTop: (scroll) }, 200); 
    }

}




// when using "on"  'expand' seems to fire before it's actually expanded. 
// el_height will then be height of closed collaps. won't work.

$('#boats,#cars').live('expand', function(e){ smart_scroll(e.target); });

$('#offset').live('expand', function(e){ 
  smart_scroll( e.target, $('#header').height() + 20 ); 
});

@toddparker

Thanks for the suggestion and demo - looks good. Would you be able to submit this as a pull request with this added as an option so we can review this?

@pillex
pillex commented Dec 21, 2012

i'm new to github. did a fork, but have no idea where to put the code...

@jaspermdegroot
Member

@toddparker

Do you think "smart scroll" should be an option, maybe including the possibility to turn it off at a certain screen width like we do for transitions? Another solution could be to put the code as it is in a separate file and people could exclude it when using the download builder.

@jaspermdegroot
Member

I removed the feature request label and 1.4 milestone from (closed) ticket #2167.

@gabrielschulhof
Collaborator

Sounds like an extension might be the way to go ...

@consciousimages

I didn't have much luck with this one, ticket #2167 worked better for me - though it isn't compatible with a "data-position="fixed" header.

live() is removed in latest versions of jQuery so must use .on() with recent versions of jQuery Mobile.

@anthonyac

I have been using this with great success. +1 for including this in some form if possible as it provides for a greatly improved UX.

@consciousimages - Try the following:

offset = $.mobile.activePage.children($("div:jqmData(role='header')")).height();

then call the function like this:

$(document).on('expand', function(e){ smart_scroll(e.target); });

@consciousimages

@anthonyac - you are a superhero. This works much better than the previous ticket I cited. The issue must have been in how I was calling it.

love the code to work with the fixed header... 👍

And a definite +1 here as well for inclusion, it's easy on a smaller mobile to "get lost" in the accordion...

@jaspermdegroot
Member

Closing as feature request. We are going to update the roadmap. If we decide to implement the feature we will set a specific milestone. The ticket will be re-opened when we are going to work on implementing the feature.

@AgDude
AgDude commented Oct 24, 2013

The above function fails for a collapsible set which has an open collapsible higher in the list. Here is a patch which attempts to fix that. Insert this just below the "var win_top = $(window).scrollTop();"

var now_open = $(el).siblings('.ui-collapsible:not(.ui-collapsible-collapsed)');
if(now_open.length > 0){
    if(now_open.offset().top < el_pos_top){
        var xtra_height = now_open.height() - now_open.children(':first').height();
        el_pos_top = el_pos_top -xtra_height;
    }
};
@anthonyac

@AgDude I'm not experiencing that issue in my case(s). Would be interesting to hear from others using this code. I am still on jQM 1.3.2

@AgDude
AgDude commented Oct 24, 2013

@anthonyac It turns out I was not calling the smart_scroll properly. I had put it in a handler on the collapsible div, if I put the handler on $(document) that problem goes away. I am using jQM 1.4b1. Thanks for your comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment