Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#8412 closed bug (wontfix)

Ajax problem on iOS with HTML5 applicationCache and web-app mode

Reported by: mfkahn@… Owned by: mfkahn@…
Priority: low Milestone: 1.next
Component: unfiled Version: 1.5.1
Keywords: Cc:
Blocked by: Blocking:

Description

This may not be a jQuery bug, however without a workaround it will affect projects such as jQuery mobile and adoption of jQuery in HTML5 apps.

On iOS (iphone/ipad etc), when a $.get is done for a resource that has been cached in the HTML5 applicationCache (applicationCache.status == 1), *and* the application is running in "web-app" mode (where the <meta name="apple-mobile-web-app-capable" content="yes"> is present in the main page, as opposed to normal "safari"/browser mode), the http status of a successful request will be set to 0 (zero), not 200.

This forces the jQuery error handler to be called. We have had to work around this by using a low-level XmlHttpRequest instead of the jquery ajax object (not just in 1.5.1, this has been an issue for a while). It might be a significant issue for developer usability on iOS, esp for jQueryMobile. Not sure if there is a bug logged at ADC about this or not.

Steps to reproduce:


  • create an HTML5 app with a cache-manifest file, using an index.html page with the <meta name="apple-mobile-web-app-capable" content="yes"> tag.
  • create a second something.html file, listing it in the CACHE section (or default section) of the manifest
  • onReady (or whenever), do a $('#something').load('something.html').
  • try this on any compatible desktop browser (safari, chrome, firefox) - should Works
  • try this on iOS safari (iPad/iPod) - should work
  • in iOS/safari, click "bookmark", then "add to home screen". Go to the device home screen and launch the app in full screen mode by tapping the tile. - won't work, the content won't be loaded and if you attach an error handler you'll see the http status from the xhr was 0, but the correct content was returned (last reproduced in iOS 4.1.2 on iPad).

Change History (16)

comment:1 Changed 8 years ago by addyosmani

Owner: set to mfkahn@…
Priority: undecidedlow
Status: newpending

Thanks for submitting a ticket to the jQuery Bug Tracker.

With respect to us evaluating this particular issue, are you able to supply us with a test case (either on jsFiddle or probably more suitably in this scenario a zip/attachment incl cache manifests) that demonstrates what you've reported?

If so, this would greatly decrease the amount of time before we're able to confirm whether or not this is an issue we may address with jQuery core.

comment:2 Changed 8 years ago by jaubourg

You could try and set the isLocal global ajax settings to true in that case:

jQuery.ajaxSetup({
    isLocal: true
});

These environment where every request, successful or not, always return a 0 status code are, simply put, impossible to deal with in a general fashion (if we fix for them, we break all the others). So, until the devs behind these totally absurd xhr implementations get back to their senses, I'm afraid there will be some need for trickeries on the part of users, sadly. ;)

comment:3 Changed 8 years ago by anonymous

Thanks for the feedback - I have sent the issue to ADC as well, but no reply yet.

comment:4 Changed 8 years ago by anonymous

This has been logged to apple as ADC bug # 9092131

There is a working example attached in a zipfile that demonstrates the issue.

comment:5 Changed 8 years ago by jaubourg

Resolution: wontfix
Status: pendingclosed

OK, so we'll wait and see if and when this is fixed in iOS.

comment:6 Changed 8 years ago by dominic@…

mfkahn, do you have a work-around that you could share? We're hitting the wall on this issue too.

comment:7 Changed 8 years ago by mfkahn@…

No, sorry. We've been using two design-around approaches:

1) low-level XMLHttpRequest, when we're certain the resource will be cached properly and absolutely must AJAX load it 2) using navigator.onLine detection and storing resources fetched with $.ajax while online in the localStorage, thereby avoiding the $.ajax call altogether when offline. This actually works better anyways since you can re-use dumbed-down, more generic manifest files for multiple pages that need to work offline.

I have cross-reported this bug to the jQuery Mobile team, I think this will be worth looking into for them, its a pretty nasty issue to support and explain to users.

comment:8 Changed 8 years ago by mfkahn@…

Here is the update from ADC on this issue, who claim the behaviour is correct according to the HTML5 spec, and so they do not intend to fix. So I think this should be re-opened as a jQuery core bug, as nobody will be able to use jQuery or jqMobile to write ajax apps for iOS or any other device else that interprets the spec in this way.

Hi,

This is a follow-up to Bug ID# 9092131.

Engineering has determined that this issue behaves as intended based on the following information:

This is the correct behavior. In offline mode, there is no actual HTTP request being made, so it would be incorrect to report a status as if there was one. For this to change, we'd have to get this behavior written into the appropriate spec (ie: HTML5).

comment:9 Changed 8 years ago by anonymous

There's a very simple solution for this. Add this to your DOM "ready" event function:

 if (window.navigator.standalone) jQuery.ajaxSetup({isLocal:true});

comment:10 Changed 8 years ago by anonymous

The fix works on iOS, not certain if there is any effect on other platforms. NETWORK: sections in a cache manifest still load properly too.

Thanks for isLocal in jQuery 1.5.1!

comment:11 Changed 8 years ago by jammus@…

A similar issue is being discussed on jQueryMobile. One possible problem with the workaround posted is that the appcache can be used when not in standalone mode (at least as far as I understand) therefore a check for navigator.standalone might not be sufficient. Has anyone else experienced the issue when in browser mode?

jqm ticket: https://github.com/jquery/jquery-mobile/issues/1579#comment_1264369

comment:12 Changed 8 years ago by jfalter0

I am experiencing a similar problem, which has had me stumped for days. I am working with jQuery 1.6.4, on an iPad 1, using Safari on iOS 5.0. I have set up my app to be stored in the application storage on the iPad. However, I have a number of Ajax calls which must get information from PHP on the web server, information that cannot be cached on the device. When the app runs on any of the desktop browsers, including Safari on Windows 7 emulating an iPad running Safari iOS 4.3.3, it works as expected. However, on the iPad, it does not.

When I check the web server system logs, the iPad is not issuing an Ajax call (using $.ajax()) to the server. I am getting status = 0, as mentioned in other notes on this ticket, but with an empty string for responseText (which I assume is because the PHP file in question is not on the local device.

comment:13 Changed 8 years ago by digitalfreak

I encounter the similar problem, but I have solved it by adding the following to the manifest file, see if this could apply to your case

NETWORK:
*

comment:14 Changed 7 years ago by anonymous

As mentioned on http://stackoverflow.com/questions/5824549/, you can also test jqXHR.responseText in the error handler to see if there was a response. When I design using applicationCache, I now routinely just test the jqXHR.responseText in the case that status==0 (which it will when the files are fetched from the cache).

comment:15 Changed 7 years ago by anonymous

Adding the NETWORK wildcard also worked for me on FireFox 16.0.2. This is weird behavior for sure.

comment:16 in reply to:  15 Changed 7 years ago by soundspawn@…

Replying to anonymous:

Adding the NETWORK wildcard also worked for me on FireFox 16.0.2. This is weird behavior for sure.

I too ran in to this today, had been fighting it for hours. Once I managed to get the manifest to update in Chromium things started working as expected.

Note: See TracTickets for help on using tickets.