How to open Safari from a WebApp in iOS 7

32,813

Solution 1

Having an anchor tag with target _blankwill work in iOS 7.0.3 but using window.open will not work and will remain to open within the webview in 7.0.3:

window.open('http://www.google.com/', '_blank');

Solution 2

Update 10/23/13: Fixed in iOS 7.0.3. Add a target="xxx" attribute to your links to do this. Also works with mailto: and friends.

This is a bug in iOS 7.0, 7.0.1 and 7.0.2 and there's no known way to do this.

It's a regression from earlier versions of iOS, where links that open in Safari work just fine. It appears to be a part of a cluster of problems revolving around opening URLs, with no external URL schemes working (for example "mailto:" doesn't work either).

The usual suspects of working around a problem like this unfortunately don't work (for example using a form and submitting it with a target of "_new").

There's other grave issues, like alert and confirm modal dialogs not working at all.

It may help to submit these as bugs to Apple, http://bugreport.apple.com

Solution 3

This is a known issue for the last couple months of betas. There are no work arounds, and from what I can tell Apple has been silent on any ETAs on fixes, or even recognizing it's a bug. Bug reports have been submitted, but not updated/responded to.

More: http://www.mobilexweb.com/blog/safari-ios7-html5-problems-apis-review

Solution 4

UPDATE Just wanted to let any one following this know that iOS 7.0.3 seems to fix the issue. I've keep standalone webapps saved for testing and the update released today restored external link/app functionality. So I've updated my code to let customers know to update their phones instead of deleting and re saving the web app.


I was going to just add a comment but apparently this is too long.

Apple set the stage for a WebApp world when they allowed chromeless webapps to be saved to the homescreen of the device. This "bug" feels like a major step backwards. It doesn't seem very apple to leave such a gapping bug in a final release. At least not one that, once they become aware of it, they don't publicly state they are working on a fix for it like they did with the lockscreen bypasses. I can't help that this feels intentional though there doesn't seem to be a clear reason why.

For developers dealing with this issue the only solution I could find was to

1st) Set the meta tag apple-mobile-web-app-capable to "no" - this prevents future users from dealing with the problem

2nd) Updated the code in our webapp to look for "standalone" and iOS version 7+. When conditions are meet I offered a popup that stated the issue and added a link to that page and asked the users for their forgivness and requested they copy the link and paste in in safari.

I wrapped the link in edge to edge tag with line breaks above and bellow to help make the copy and pasting process of the url a bit easier.

Solution 5

I found two solutions for the time being to this problem, both of which obviously using preventDefault on the external links.

If you're linking to another website or something to download, the only option I see is to ironically alert the user to hold their finger on the link to get the touch callout prompt. Then again, depending if it's a website or a PDF, instruct them to either copy the link or in the case of a PDF, add it to their reading list. Since the alert and confirm modals are also broken you'll need to implement your own modal notifications. If you already have that it shouldn't be that much trouble.

Update [2013-10-25] Apparently it's been fixed in iOS 7.0.3 and links open in Safari...

Edit [2013-10-05] Here's pretty much what I use with a jQuery UI modal

// iOS 7 external link polyfill
$('a[rel=external], a[rel=blank], a[target=_blank], a[href$=".pdf"]').on('click', function(e) {

  if (navigator.standalone && /iP(hone|od|ad) OS 7/.test(navigator.userAgent)) {
    e.preventDefault(); e.stopPropagation();

    var href = $(this).attr('href');

    var $dialog = $('<div id="ios-copy"></div>')
      .html('<p>iOS 7 prevents us from opening external links in Safari, you can continue to the address and risk losing all navigation or you can copy the address to your clipboard by <strong>holding your finger on the link</strong> for a few seconds.</p><p><a style="background-color: rgba(0,0,0,.75); color: #fff; font-size: 1.25em; padding: 1em;" href="' + href + '">' + href + '</a></p>')
      .appendTo('body')
      .dialog({
        title: 'External link',
        modal: true,
        buttons: {
          Ok: function() {
            $( this ).dialog( "close" );
          }
        }
      });
  }
});

The other workaround is using ajax or an iframe to load the external content, but unless you have a good sub-browser or something in your app it will look sketchy. Here's something along those lines.

// iOS 7 external link polyfill
if (/iP(hone|od|ad) OS 7/.test(navigator.userAgent) && window.navigator.standalone) {
  $('a[rel=external], a[href$=".pdf"]').on('click', function(e) {
    e.preventDefault(); e.stopPropagation();

    var link = this;
    var href = $(link).attr('href');

    var frameContainer = $('<div></div>').css({
      position: 'absolute',
      left: 10,
      top: $(link).position().top,
      opacity: 0,
      overflow: 'scroll',
      '-webkit-overflow-scrolling': 'touch',
      height: 520,
      transition: 'opacity .25s',
      width: 300
    });

    var iosFrame = $('<iframe class="iosFrame" seamless="seamless" width="1024" height="5000"></iframe>')
      .attr('src', href)
      .css({
        height: 5000,
        'max-width': 1024,
        width: 1024,
        overflow: 'scroll !important',
        '-webkit-overflow-scrolling': 'touch !important'
      });

    var iosFrameClose = $('<a href="#"><i class="icon-cancel icon-remove icon-3x"></i></a>').css({
      position: 'absolute',
      left: -10,
      top: $(link).position().top - 20,
      'text-shadow': '1px 1px 1px #000',
      transition: 'opacity .25s',
      opacity: 0,
      '-webkit-transform': 'translate3d(0, 0, 0)',
      width: '3em',
      height: '3em'
    }).on('click', function(e) {
      e.preventDefault();
      setTimeout( function() {
        $(frameContainer).remove();
        $(iosFrameClose).remove();
      }, 250);
    });

    iosFrame.appendTo(frameContainer);
    frameContainer.appendTo('body');
    iosFrameClose.appendTo('body');

    iosFrame.contents().css({
      '-webkit-transform': 'translate3d(0, 0, 0)'
    });

    // Show this thing
    setTimeout( function() {
      $(frameContainer).css({ opacity: 1 });
      $(iosFrameClose).css({ opacity: 1 });
    }, 1);
  });
}
Share:
32,813
Joshua Smith
Author by

Joshua Smith

Updated on January 12, 2020

Comments

  • Joshua Smith
    Joshua Smith over 4 years

    In previous versions of iOS, <a> tags would open Mobile Safari, and you had to intercept those to instead stay inside the webapp (an HTML page that has been saved to the home screen by the user).

    Starting in iOS 7, all links are staying inside the WebApp. I cannot figure out how to get it to open Safari, when I really want it to.

    I've tried using window.open and a target="_blank" but neither works.

    Here is a sample. https://s3.amazonaws.com/kaontest/testopen/index.html

    If you save that to your home screen in iOS 6, the link opens Safari. But in iOS 7, it doesn't.

    Note that this is the OPPOSITE question that everyone is usually asking ("how to NOT open Safari"). That behavior seems to be the new default, and I can't figure out how to get the old behavior back!