web-dev-qa-db-fra.com

Comment ouvrir Safari à partir d'une WebApp dans iOS 7

Dans les versions précédentes d'iOS, <a> les balises ouvriraient Mobile Safari, et vous deviez les intercepter pour rester à l'intérieur de la webapp (une page HTML qui a été enregistrée sur l'écran d'accueil par l'utilisateur).

À partir d'iOS 7, tous les liens restent à l'intérieur de la WebApp. Je ne peux pas comprendre comment le faire ouvrir Safari, quand je le veux vraiment.

J'ai essayé d'utiliser window.open et a target="_blank" mais ni ne fonctionne.

Voici un exemple. https://s3.amazonaws.com/kaontest/testopen/index.html

Si vous enregistrez cela sur votre écran d'accueil dans iOS 6, le lien ouvre Safari. Mais dans iOS 7, ce n'est pas le cas.

Notez que c'est la question OPPOSÉE que tout le monde pose habituellement ("comment NE PAS ouvrir Safari"). Ce comportement semble être le nouveau par défaut, et je n'arrive pas à comprendre comment récupérer l'ancien comportement!

31
Joshua Smith

Avoir une balise d'ancrage avec la cible _blank fonctionnera dans iOS 7.0.3 mais l'utilisation de window.open ne fonctionnera pas et restera à ouvrir dans la vue Web dans 7.0.3:

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

Mise à jour 23/10/13: corrigé dans iOS 7.0.3. Ajoutez un attribut target = "xxx" à vos liens pour ce faire. Fonctionne également avec mailto: et amis.

Il s'agit d'un bogue dans iOS 7.0, 7.0.1 et 7.0.2 et il n'y a aucun moyen connu de le faire.

C'est une régression par rapport aux versions antérieures d'iOS, où les liens qui s'ouvrent dans Safari fonctionnent très bien. Il semble faire partie d'un groupe de problèmes liés à l'ouverture d'URL, sans aucun schéma d'URL externe (par exemple, "mailto:" ne fonctionne pas non plus).

Les suspects habituels de contourner un problème comme celui-ci ne fonctionnent malheureusement pas (par exemple, en utilisant un formulaire et en le soumettant avec la cible "_new").

Il y a d'autres problèmes graves, comme les dialogues modaux d'alerte et de confirmation qui ne fonctionnent pas du tout.

Il mai aide à soumettre ces bogues à Apple, http://bugreport.Apple.com

25
thomasfuchs

C'est un problème connu pour les deux derniers mois de bêtas. Il n'y a pas de solution, et d'après ce que je peux dire Apple a gardé le silence sur les ETA sur les correctifs, ou même en reconnaissant qu'il s'agissait d'un bogue. Des rapports de bogues ont été soumis, mais pas mis à jour/répondu .

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

6
Rob Porter
window.open('http://www.google.com/'); // stays in web app view

<a href='http://www.google.com/' target='_blank'>Click Here</a> // opens in safari

Si vous souhaitez ouvrir Safari, mais que l'utilisation d'une balise d'ancrage comme celle-ci n'est pas possible pour une raison quelconque, la solution JavaScript à cette question s'ouvrira également dans Safari .

1
Brett Clapper

iOS v7.0.3 publié le 22/10/13 résout le problème.

1
Ed Lee

MISE À JOUR Je voulais juste faire savoir à quiconque suivant cela qu'iOS 7.0.3 semble résoudre le problème. J'ai conservé les applications Web autonomes enregistrées pour les tests et la mise à jour publiée aujourd'hui a restauré la fonctionnalité de lien/application externe. J'ai donc mis à jour mon code pour informer les clients de la mise à jour de leur téléphone au lieu de supprimer et de réenregistrer l'application Web.


J'allais juste ajouter un commentaire mais apparemment c'est trop long.

Apple a ouvert la voie à un monde WebApp en autorisant l'enregistrement des applications Web sans chrome sur l'écran d'accueil de l'appareil. Ce "bug" ressemble à un grand pas en arrière. Il ne semble pas très Apple laisser un tel bogue dans une version finale. Du moins pas sur lequel, une fois qu'ils en ont conscience, ils ne déclarent pas publiquement qu'ils travaillent sur un correctif comme ils l'ont fait avec les contournements de l'écran de verrouillage. Je ne peux pas m'empêcher que cela semble intentionnel bien qu'il ne semble pas y avoir de raison claire pourquoi.

Pour les développeurs confrontés à ce problème, la seule solution que j'ai pu trouver était de

1er) Réglez la balise META Apple-mobile-web-app-capable sur "non" - cela empêche les futurs utilisateurs de traiter le problème

2e) Mise à jour du code dans notre webapp pour rechercher "autonome" et iOS version 7+. Lorsque les conditions sont réunies, j'ai proposé une fenêtre contextuelle qui a signalé le problème et ajouté un lien vers cette page et demandé aux utilisateurs leur pardon et leur a demandé de copier le lien et de le coller dans safari.

J'ai encapsulé le lien dans la balise Edge to Edge avec des sauts de ligne ci-dessus et ci-dessous pour faciliter le processus de copie et de collage de l'URL.

1
JDubDev

Pour l'instant, j'ai trouvé deux solutions à ce problème, toutes deux utilisant évidemment preventDefault sur les liens externes.

Si vous créez un lien vers un autre site Web ou quelque chose à télécharger, la seule option que je vois est d'alerter ironiquement l'utilisateur de tenir son doigt sur le lien pour obtenir l'invite de la légende tactile. Ensuite, selon qu'il s'agit d'un site Web ou d'un PDF, demandez-leur de copier le lien ou, dans le cas d'un PDF, de l'ajouter à leur liste de lecture. Étant donné que les modes d'alerte et de confirmation sont également interrompus, vous devrez implémenter vos propres notifications modales. Si vous l'avez déjà, cela ne devrait pas vous poser de problème.

Mise à jour [2013-10-25] Apparemment, cela a été corrigé dans iOS 7.0.3 et les liens ouverts dans Safari ...

Edit [2013-10-05] Voici à peu près ce que j'utilise avec un modal jQuery UI

// 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" );
          }
        }
      });
  }
});

L'autre solution consiste à utiliser ajax ou un iframe pour charger le contenu externe, mais à moins que vous n'ayez un bon sous-navigateur ou quelque chose dans votre application, il aura l'air sommaire. Voici quelque chose dans ce sens.

// 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);
  });
}
1
caktux