Skip to content

Loading…

Blank page when F5 is pressed while navigating down through a nested list #2709

Closed
stodge opened this Issue · 11 comments

9 participants

@stodge

If I browse through a nested list to a sub "page", all is well. If I hit F5 to refresh the page is blank. Try it on the jquery mobile demo site.

Is there way to handle this?

@toddparker

I think this was broken when we made changes around B3, we need to figure out how to make this work...

@jasonhayes

I have an android and an iPhone and I can't figure out how to map F keys to either to test this. Is this something the normal mobile user would have to worry about?

@eddiemonge

Bexol: F5 is the refresh key on a desktop computer. For mobile phones, a simple page refresh is the same thing.

@tec27

This is due to an exception being thrown by the selector in loadPage:

// If we failed to find the page, check to see if the url is a
// reference to an embedded page. If so, it may have been dynamically
// injected by a developer, in which case it would be lacking a data-url
// attribute and in need of enhancement.
if ( page.length === 0 && dataUrl && !path.isPath( dataUrl ) ) {
    page = settings.pageContainer.children( "#" + dataUrl )
    .attr( "data-" + $.mobile.ns + "url", dataUrl )
}

When you hit the page on the refresh, your data-url will be something like &ui-page=6. This isn't a valid jQuery selector due to the ampersand (although for some reason jQuery will allow you to put ampersands anywhere else in the string, which is why inserting the p in eddiemonge's URL works). Thus, jQuery throws a syntax error and the page loading stops, meaning the list never actually gets mobile-enhanced.

I'm not sure what the best approach to fixing this is, but escaping &'s would do the trick, as would catching exceptions around that if.

Also, if anyone needs a quick fix for this issue while waiting for the actual fix, disabling pushState will do the trick (since you can then be guaranteed to always have something in front of the & in your hash).

@cggit

The example above where having a character between the # and & brings you back to the root of the list. The temp solution of disabling pushState causes strange back button behavior as a nested refresh is recorded as a history state but you find yourself at the root which isn't recorded.

Is there a way to stay on the nested list after a refresh?

@cggit

I somewhat solved my issue with http://stackoverflow.com/questions/10776342/jquery-mobile-nested-list-refresh-solution
Its not pretty but does what i need. I invite anyone to make it more reliable/robust and please share.

@naofumi

I think that the issue with the data-url not being a valid CSS selector is only part of the problem.

jQM queries for the subpage in query.mobile.navigation.js #681

// Check to see if the page already exists in the DOM.
        page = settings.pageContainer.children( ":jqmData(url='" + dataUrl + "')" );

However, at this point the pagecreate event has not yet fired and the widgets have not yet been initialized.
This means that the subpages for the nested views haven't been created either.

Unless we create the subpages before we do a pageload, we won't be able to navigate to a subpage because is simply won't be there in the DOM yet.

@naofumi

Updated code for part 3

I think I've got a solution working.

There are 3 parts to it.

1. The IDs in the subpages generated by nested lists were missing.

In the _createSubPages function in widgets/listview.js line 357, we create the page with

  .wrap( "<div " + dns + "role='page' " +   dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )

The ID for the div is missing so we fix this to

   .wrap( "<div " + "id='" + id + "' " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )

2. The valid CSS selector issue mentioned by tec27

Actually, this error occurs only because of the issues in 1. and 3., and is not required to solve the nested list issue per se. Still, we use a regex to escape invalid CSS selectors in the code that tec27 mentioned.

jquery.mobile.navigation.js line 689

if ( page.length === 0 && dataUrl && !path.isPath( dataUrl ) ) {
     page = settings.pageContainer.children( "#" + dataUrl.replace(/(&|=)/g, '\\$1'))
       .attr( "data-" + $.mobile.ns + "url", dataUrl );
    }

3. Reload the subpage after initializing and showing the parent page.

As I mentioned in my previous comment, in order to navigate directly to a subpage, we have to initialize it first. When the first loadPage is fired, the widgets have not been initialized yet, so the subpages don't exist. This means that we can't show a subpage on the first loadPage.

When we request a subpage like "http://jquerymobile.com/demos/1.1.0/docs/lists/lists-nested.html#&ui-page=0-7" via a refresh, what happens is the loadPage looks for "lists-nested.html#&ui-page=0-7" in the DOM (first in the data-url and then in the id), but can't find it because the listview widget has not yet been initialized. As a last resort, it displays the first page in the DOM which is generally the root page of the nested listview. Of course this assumes that issues 1 and 2 have been resolved.

As a workaround, we do a second loadPage just before we show the parent page (on the pagebefore show event after all the widgets have been initialized).

Add the following code anywhere convenient.

$(document).live('pagebeforeshow', function(event){
  var isDialog = location.hash.indexOf($.mobile.dialogHashKey) > -1,
      doesActivePageMatchHash = (location.hash == '#' + $('.ui-page-active').data('url'));
  if (location.hash && !isDialog && !doesActivePageMatchHash) {
    $.mobile.changePage(location.href, {transition: 'none'});
  }
});

This will check the current location.hash if available, and compare it the 'data-url' attribute of the currently active page. If they don't match (meaning that we wanted a subpage, but the parent page is currently being shown), then we changePage to the location in the location.href. Since the subpages have been initialized by this time, we can successfully navigate to the correct subpage.

Update
Changed the event to 'pagebeforeshow' and the transition to 'none' in part 3 so the parent page will not be shown at all.

@johnbender johnbender was assigned
@toddparker

@johnbender - this is another one I wanted to check on for 1.3. Is this on your radar or should we move it out?

@jaspermdegroot
jQuery Foundation member

@johnbender @toddparker

When testing "Nested list" (http://jquerymobile.com/test/docs/lists/lists-nested.html) > "Animals" > F5/refresh I didn't get a blank page, but returned to "Nested list" (url: ../lists-nested.html#&ui-page=0-8).

Same result when testing 1.2. On 1.1.1 it breaks: Uncaught Error: Syntax error, unrecognized expression: #&ui-page=0-8.
Both versions of the docs use core 1.7.1.

Closing as fixed.

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.