I’m developing a website that will work with mobile safari in offline mode. I'm able to bookmark it to the home screen and load it from there. But, once opened from the home screen, clicking on certain links will jump out of the app and open in mobile safari – despite the fact that I preventDefault() on all link clicks!
The app binds an onclick event handler at the <body>
level. Using event delegation, it catches any click on any link, looks at its href (eg 'help' or 'review'), and dynamically calls a javascript template and update the pages. The event handler calls preventDefault() on the event object – for some of the links this works, and the page is updated with the template output. However, for the links that result in a hit against the local database before outputting the results of the template, the links are opened in mobile safari.
In desktop safari, all the links work even when i’m offline – something is happening that’s mobile safari specific.
Any thoughts on why some links would work offline, but not others? None of the link URLs in question are listed in the manifest file, but they don’t (shouldn't) need to be since the link action is prevented.
a couple extra oddities:
* once I click on a a link that loads in mobile safari, even if I'm offline, those same links now work, and the templates populated with data from the db work properly. in other words: the links fail when opened from the home screen, but not from within mobile safari offline
* changing the link to remove the database hit (populating the template with a mock db result) solves the problem, and the links can be clicked in the app from the home screen.
You may want to take a look at this: https://gist.github.com/1042026
// by https://github.com/irae
(function(document,navigator,standalone) {
// prevents links from apps from oppening in mobile safari
// this javascript must be the first script in your <head>
if ((standalone in navigator) && navigator[standalone]) {
var curnode, location=document.location, stop=/^(a|html)$/i;
document.addEventListener('click', function(e) {
curnode=e.target;
while (!(stop).test(curnode.nodeName)) {
curnode=curnode.parentNode;
}
// Condidions to do this only on links to your own app
// if you want all links, use if('href' in curnode) instead.
if('href' in curnode && ( curnode.href.indexOf('http') || ~curnode.href.indexOf(location.host) ) ) {
e.preventDefault();
location.href = curnode.href;
}
},false);
}
})(document,window.navigator,'standalone');
I got it to work, the problem was due to an unseen error in the event handler code (unrelated to stopping the link from being followed). If you bind an event handler for click events to the body tag, and call preventDefault(), then the link will not be followed and mobile safari will not open, and you can define you own logic for updating the page based on that link url.
You should be sure that you call preventDefault() before any errors could possibly occur - the problem in my case was that an error was occurring in the event handler before preventDefault() was called, but of course I couldn't see that error in the console because the link had already been followed.
Here's the code I'm using (it assumes DOM standard events and would fail in IE):
bodyOnClickHandler = function(e) {
var target = e.target;
if (target.tagName == 'A') {
e.preventDefault();
var targetUrl = target.getAttribute("href");
//show the page for targetUrl
}
}