Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I scroll to a page element in jQuery Mobile?

I have a long jQuery mobile page and would like to scroll to an element halfway down this page after the page loads.

So far I've tried a few things, the most successful being:

jQuery(document).bind("mobileinit", function() {
  var target;
  // if there's an element with id 'current_user'
  if ($("#current_user").length > 0) {
    // find this element's offset position
    target = $("#current_user").get(0).offsetTop;
    // scroll the page to that position
    return $.mobile.silentScroll(target);
  }
});

This works but then the page position is reset when the DOM is fully loaded. Can anyone suggest a better approach?

Thanks

like image 641
bodacious Avatar asked Dec 13 '22 08:12

bodacious


1 Answers

A bit late, but I think I have a reliable solution with no need for setTimeout(). After a quick look into the code, it seems that JQM 1.2.0 issues a silentScroll(0) on window.load for chromeless viewport on iOS. See jquery.mobile-1.2.0.js, line 9145:

    // window load event
    // hide iOS browser chrome on load
    $window.load( $.mobile.silentScroll );

What happens is that this conflicts with applicative calls to silentScroll(). Called too early, the framework scrolls back to top. Called too late, the UI flashes.

The solution is to bind a one-shot handler to the 'silentscroll' event that calls window.scrollTo() directly (silentScroll() is little more than an asynchronous window.scrollTo() anyway). That way, we capture the first JQM-issued silentScroll(0) and scroll to our position immediately.

For example, here is the code I use for deep linking to named elements (be sure to disable ajax load on inbound links with data-ajax="false"). Known anchor names are #unread and #p<ID>. The header is fixed and uses the #header ID.

$(document).bind('pageshow',function(e) {
    var $anchor;
    console.log("location.hash="+location.hash);
    if (location.hash == "#unread" || location.hash.substr(0,2) == "#p") {
        // Use anchor name as ID for the element to scroll to.
        $anchor = $(location.hash);
    }
    if ($anchor) {
        // Get y pos of anchor element.
        var pos = $anchor.offset().top;

        // Our header is fixed so offset pos by height.
        pos -= $('#header').outerHeight();

        // Don't use silentScroll() as it interferes with the automatic 
        // silentScroll(0) call done by JQM on page load. Instead, register
        // a one-shot 'silentscroll' handler that performs a plain
        // window.scrollTo() afterward.
        $(document).bind('silentscroll',function(e,data) {
            $(this).unbind(e);
            window.scrollTo(0, pos);
        });
    }
});

No more UI flashes, and it seems to work reliably.

like image 150
fbonnet Avatar answered Dec 21 '22 23:12

fbonnet