Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

'Error loading page' when opening a page specified in appcache manifest (iPhone) #1579

Closed
jammus opened this Issue · 46 comments
@jammus

Supporting files: https://gist.github.com/959332

Steps to reproduce:

Open index.html on iPhone.
Click add to home screen.
Click on newly created icon.
Browse to 'read more'.

What should happen:

Otherpage.html should be loaded from the appcache.

What happens instead:

'Error loading page'.

Some googling has turned up this diagnosis from Stackoverflow: http://stackoverflow.com/questions/5824549/cannot-access-manifest-cached-files-with-ajax-from-webapp-saved-to-home-screen-in

"Apparently, when trying to use $.ajax() in offline mode, the request successfully fetches the cached files, but it returns 0 on XHMLHttpRequest.status. Having read up on this, I have seen that a status code of 0 can be returned when the user is offline and even when requesting local files. However, a successful GET should report a status code between 200 and 300. Perhaps $.ajax() checks for a 200-300 status, otherwise the request is considered to have failed."

Checking the value of jqXHR.responseText in the error handler of the ajax request shows the contents of otherpage.html.

The same issue also appears to affect Android (2.2 tested).

@jblas

@jammus

What version of jQuery Core and jQuery Mobile are you using?

@jammus

Sorry, my bad. jQuery 1.6 and jQM was built from master some time this morning.

@jblas

@jammus: There were some problems with loading local files this morning that we've since fixed. Can you update and try the newer source?

@jammus

@jblas: Sure thing. Done and reset the simulator - still getting the same issue on the iPhone. (Can't retest Android at the moment)

@jammus

@jblas: Finally managed to retest on Android - still experiencing the same issue.

@jcorporation

This is the same issue and the patch provided works for me with offline manifest
#926

@jammus

@jcorporation: Thanks for the info. The issue is certainly similar. However the success callback isn't firing for me, only the error callback.

The line mentioned in the other ticket has since changed though so it maybe I'm looking in the wrong place.

@jcorporation

Right, the line changed, you should try the patch. My symptom was an endless loading message.

@jammus

The symptom here is the yellow 'Error loading page' message. The patch won't work in this case as the success callback of the ajax request in changePage is not called when loading a page stored in the appcache.

@hakanson

Looks similar to jQuery bug #8412. I wonder if an ajax prefilter that treats offline like other local protocols would work?

$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
  // treat offline like file: protocol
  if ( navigator.onLine && navigator.onLine === false ) {
    options.isLocal = true;
  }
});

Here is a snippet of the jQuery ajax code that would get triggered when isLocal is true and status is 0.

// If the request is local and we have data: assume a success
// (success with no data won't get notified, that's the best we
// can do given current implementations)
if ( !status && s.isLocal && !s.crossDomain ) {
    status = responses.text ? 200 : 404;
@jammus

@hakanson Thanks for the link. That appears to be the exact issue we're experiencing.

The prefilter looks like a potential solution. I don't think navigator.onLine is the suitable value to check though as the appcache can be used even if the device is online. Under iOS navigator.standalone, which indicates if the site has been launched as a web app, is a better option. Not sure it's ideal though as there may be other circumstances where the appcache is hit.

@jammus

Maybe applicationCache.status is a candidate. If it's not set to UNCACHED or OBSOLETE then apply the filter.

@hakanson

Is this the same issue as jquery/jquery-mobile#1194 from @mfkahn ? That also refers to jQuery bug #8412.

@hakanson

If appcache can be used when online, then navigator.onLine won't work.

Also, if appcache can be used either from Mobile Safari or if "webpage is displayed in full-screen mode" (Hiding Safari User Interface Components), then navigator.standalone won't work.

I agree that some property of DOMApplicationCache like applicationCache.status is better.

@jammus, can you try out an ajaxPrefilter and see if it works?

@jammus

@hakanson Sure. After adding the following the 'error loading page' error is no longer shown and all pages load fine.

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (applicationCache &&
            applicationCache.status != applicationCache.UNCACHED &&
            applicationCache.status != applicationCache.OBSOLETE
        ) {
        options.isLocal = true;
    }
});
@jammus

Actually, it might not be working perfectly. Going back to it now I'm getting the same error as before but not every time. I'll do some more digging.

@mfkahn

See http://bugs.jquery.com/ticket/8412 , someone has posted a workaround that uses the 1.5.1+ isLocal setting for ajax. Seems to fix the issue, at least on iOS, I did not check android.

@jammus

As a follow up to my previous comment the resurfacing of the error was due to entirely different issue so I'm now confident that the above fix works.

@mfkahn Thanks for the update. We earlier debated the use of navigator.standalone, however as the cache manifest can also be used in browser mode we weren't sure it was entirely suitable. Maybe the workaround should include both. I'll cross post to that ticket and see if anyone has more input.

@mfkahn

If it helps - on that ticket (http://bugs.jquery.com/ticket/8412) I had posted a link to the same issue I'd logged to ADC. The ADC issue report contains an example that can be used to demonstrate the issue. When I add the isLocal fix to the example the app works the same in both modes (web-app/browser). I was surprised, from reading the jquery docs I had assumed the isLocal setting would have fixed the items in the CACHE section but broken items in the NETWORK section, but it seems fine.

@toddparker

Just following up here...is this still an open issue?

@ksksks

This issue is still not solved and is a big problem.
Sites using ajax for loading stop working when a cache manifest is defined.
Wether the prefilter

$(document).ready(function () {
    $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
        options.isLocal = true;
    });
});

nor a plain

$(document).ready(function () {
    jQuery.ajaxSetup({isLocal:true});
});

works for me on Android (GalaxyTab v2.2, Defy v2.3) or in Firefox 6.0.

@jblas jblas was assigned
@toddparker

Just bumped up the priority here since it sounds like it's still unresolved.

@johnbender

Doing my best to get caught up here and I have a few questions (bear with me):

@jammus

In your snippet

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (applicationCache &&
            applicationCache.status != applicationCache.UNCACHED &&
            applicationCache.status != applicationCache.OBSOLETE
        ) {
        options.isLocal = true;
    }
});

won't this treat any and all requests as file system requests even when they aren't request to the cache or file system so long as the app cache is valid? So if the user is online, the cache is valid, and he/she makes a request for a page not listed in the manifest it really should be requested as normal (ie not isLocal). Again, I'm just eyeballing it so if I'm off course you'll have to forgive me.

@hakanson and @ksksks I would ask the same of both:

$(document).ready(function () {
    $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
        options.isLocal = true;
    });
});

and

$(document).ready(function () {
    jQuery.ajaxSetup({isLocal:true});
});

isLocal appears to make sense when you can verify that the user cannot make web requests and should only be able to retrieve the material from the cache. If you look at the jquery xhr handling the reason this seems to work is that, right now, it only really cares about isLocal for coercing the status into something sane when the value is 0 and not cross domain.

https://github.com/jquery/jquery/blob/master/src/ajax/xhr.js#L167

@johnbender johnbender was assigned
@johnbender

This is also probably a good place to note for people who read the above and want to use the workaround that if the request is cross domain it won't work. See (which @hakanson linked earlier):

https://github.com/jquery/jquery/blob/master/src/ajax/xhr.js#L167

@johnbender

[edit] answered my own question with a simple test.

@jammus

Hi @johnbender,

Yeah, you're right. It treats all requests as local when a cache exists. As you point out though it is a bit of a hack. Maybe the check or one similar should be pushed into xhr.js in jQuery main rather than relying purely on isLocal behaving this way forever.

Cheers,
James

@johnbender

Another quick update here:

http://dev.w3.org/html5/spec/offline.html#appcache

It looks like the manifest entries have to come from the same origin so my comment about cross domain requests not working shouldn't be an issue. I think the fact that isLocal really has nothing to do with the problem might prove dangerous since it could be used for other purposes in core.

tl;dr this will remain the workaround

@mfkahn

Has anyone identified this an issue on any platforms except iOS running in navigator.standalone=true mode?

@aiwilliams

I'm using the isLocal workaround.

I have index.html linking to welcome.html, welcome.html?v=1, and welcome.html?v=2. When I click on the first two, all's well! welcome.html is in the cache, and loads just fine, and my javascript can access the query param as undefined and 1, respectively. Yet when I click the third link, the xhr.status is 0, but the response.text is empty - therefore jQuery interprets this as a 404, and page load fails.

Why in the world would the first two links work fine, but not the third?

If I flip $.mobile.ajaxEnabled = false, then all three links work fine from the cache, but of course I lose page transitions.

This issue occurs in Safari 5.1.2. Chrome works fine, where any variance in query params still successfully loads welcome.html!

@jammus

@aiwilliams Do you have all three page in the cache manifest?

@aiwilliams

No, I was not thinking of the v=1, v=2 as being separate pages, but I can see now that they are indeed treated that way by the cache mechanism. This seems to explain why $.mobile.ajaxEnabled = false causes the links to work, since each of the two query param urls would cause a fetch to the server. There are so many things to keep up with! I think I'm good to go.

@toddparker

Sounds like we can close this issue then?

@jammus

@toddparker No, I don't think so. The original issue reported is different to the one @aiwilliams mentions here. At least as far as I understand.

@johnbender

@toddparker

I concur with @jammus. We really want to leave this one open to signal to devs that it's still an outstanding issue and they need to use the workaround.

@toddparker

Ok, sounds like a plan.

@mattberg

I recently came across this issue running Android 2.3.6. Any local pages just linked with index.html, about.html, dir/index.html all returned "Error loading page" when pulling from appcache.

So you have to choose between ajax and nice page transitions and offline capability? Seems like a pretty major issue right?

@nimy

I got offline cache downloading problem in Opera Mobile, it is not caching the files. Also getting window.applicationCache.status as always '0', when the 'turbo' setting is 'ON'. Unfortunately html5 storage (webSQL) is not working with 'turbo' 'OFF'. I need both (html5 offline caching & storage) to run my jQuery mobile application. Please help me.

@PlippiePlop

This issue is still open with JQmobile 1.1 final and jQuery1.7.1

when using ajax for page navigation on Apple Iphone devices launching from homescreen (web-app)
It shows a error popup a second but continues to next page.

@mdempfle

I can confirm this.
I have played around with different browsers and is seem that at the desktop Firefox and Chrome work fine. Also Opera on Android. It fails in the native browser of android 2.3.4 and Dolphin, Dolphin HD.

My current workaround is to use rel="external" for links.

So I agree with mattberg that this i a pretty major issue.

So is there a workaround where at least the ajax capability is not lost?

@ryanmc2033

I am experiencing the same issue. Has a workaround or fix been developed for this? I am using JQM 1.1.0 and JQ 1.7.1, and I am all on the same domain.

@frequent

I'm also in the boat, although I don't use appache/manifest at all and still get the behavior described above.

@ryanilg

Also having this issue, running 1.2.0-alpha with jQuery 1.7.2

@webslash

Can confirm this issue still exists.

Tested today on iPhone 5 (iOS6).
Exact same issue as @PlippiePlop

"Error Loading Page" shows for a second but the page does load.
Only happens when launching webapp from homescreen, works correct in safari.
Latest JQM version (1.2)

@webslash

Currently I'm using this CSS snippet to move the error message out of screen:

.ui-loader.ui-body-e {
left:-9999px !important;
}

This is obviously far from perfect, but seems to be the only way to get rid of the error message within an iOS WebApp.

There's no loading image either so UX wise the user doesn't know a new page is loading..
(except for the tiny spinner in the iOS top bar)

Anyone with a proper solution, please share ;)

@ldeluca

hey everyone, no updates on this issue in over 2 years. Is it still valid? @jammus ?

@arschmitz
Owner

Im guessing this is no longer an issue since there are no new reports if someone is still having this issue with latest code comment and we will reopen im going to close this as stale.

@arschmitz arschmitz closed this
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.