web-dev-qa-db-fra.com

iPhone Safari Web App ouvre les liens dans une nouvelle fenêtre

J'ai un problème avec le Web après avoir ajouté une icône à l'écran d'accueil. Si le site Web est lancé à partir de l’écran d’accueil, tous les liens s’ouvriront dans une nouvelle fenêtre de Safari (et perdront la fonctionnalité plein écran). Comment puis-je l'empêcher? Je n'ai pu trouver aucune aide, seule la même question restée sans réponse.

152
Pavel Linkesch

J'ai trouvé une solution JavaScript dans iWebKit framework:

var a=document.getElementsByTagName("a");
for(var i=0;i<a.length;i++)
{
    a[i].onclick=function()
    {
        window.location=this.getAttribute("href");
        return false
    }
}
107
Pavel Linkesch

Les autres solutions proposées ici ne tiennent pas compte des liens externes (que vous souhaitez probablement ouvrir à l’extérieur dans Safari) ou ne prennent pas en compte les liens relatifs (sans le domaine qu’ils contiennent).

Le projet html5 mobile-boilerplate est lié à ce Gist qui contient une bonne discussion sur le sujet: https://Gist.github.com/1042026

Voici le code final qu'ils ont trouvé:

<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.Host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>
92
rmarscher

Si vous utilisez jQuery, vous pouvez faire:

$("a").click(function (event) {
    event.preventDefault();
    window.location = $(this).attr("href");
});
46
David H.

Cela fonctionne pour moi sur iOS 6.1 et avec Bootstrap JS (menus déroulants, etc.)

$(document).ready(function(){
    if (("standalone" in window.navigator) && window.navigator.standalone) {
      // For iOS Apps
      $('a').on('click', function(e){
        e.preventDefault();
        var new_location = $(this).attr('href');
        if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined){
          window.location = new_location;
        }
      });
    }
  });
20
Sean

C'est une vieille question et beaucoup des solutions ici utilisent javascript. Depuis lors, iOS 11.3 a été publié et vous pouvez maintenant utiliser le membre de la portée . Le membre de la portée est une URL du type "/" où tous les chemins sous cette étendue n'ouvriront pas une nouvelle page.

Le membre de portée est une chaîne qui représente la portée de navigation du contexte d'application de cette application Web.

Voici mon exemple:

{
  "name": "Test",
  "short_name": "Test",
  "lang": "en-US",
  "start_url": "/",
  "scope": "/",
  ...
}

Vous pouvez également en savoir plus à ce sujet ici . Je recommande également d'utiliser le générateur qui fournira cette fonctionnalité.

Si vous spécifiez l'étendue, tout fonctionnera comme prévu avec Android, les destinations hors de l'étendue s'ouvriront dans Safari - avec un bouton de retour (le plus petit dans la barre d'état) vers votre PWA.

9
Amir Raminfar

Si vous utilisez jQuery Mobile, vous rencontrez la nouvelle fenêtre lorsque vous utilisez l'attribut data-ajax = 'false'. En fait, cela se produira chaque fois que ajaxEnabled est désactivé, via un lien externe, par un paramètre $ .mobile.ajaxEnabled ou en ayant un attribut target = ''.

Vous pouvez le réparer en utilisant ceci:

$("a[data-ajax='false']").live("click", function(event){
  if (this.href) {
    event.preventDefault();
    location.href=this.href;
    return false;
  }
});

(Merci à Richard Poole pour la méthode live () - ne travaillait pas avec bind ())

Si vous avez désactivé ajaxEnabled globalement, vous devez supprimer [data-ajax = 'false'].

Cela m'a pris assez de temps à comprendre, car je m'attendais à ce que ce soit un problème spécifique à jQuery Mobile, car ce sont les liens Ajax qui interdisaient réellement la nouvelle fenêtre.

5
Jason Prawn

Sur la base des réponses de David et du commentaire de Richards, vous devez effectuer une vérification de domaine. Sinon, des liens vers d'autres sites Web seront également ouverts dans votre application Web.

$('a').live('click', function (event)
{      
    var href = $(this).attr("href");

    if (href.indexOf(location.hostname) > -1)
    {
        event.preventDefault();
        window.location = href;
    }
});
5
Thomas Kekeisen

Ce code fonctionne pour iOS 5 (cela a fonctionné pour moi):

Dans la balise head:

<script type="text/javascript">
    function OpenLink(theLink){
        window.location.href = theLink.href;
    }
</script>

Dans le lien que vous souhaitez ouvrir dans la même fenêtre:

<a href="(your website here)" onclick="OpenLink(this); return false"> Link </a>

J'ai eu ce code de ce commentaire: balises méta de l'application web iphone

3
SerinEleven

J'ai trouvé celui qui est très complet et efficace, car il vérifie qu'il ne fonctionne que sous une application Web autonome, fonctionne sans jQuery et est simple, il vient d'être testé sous iOS 8.2:

Restez autonome: interdire les liens dans les applications Web autonomes ouvrant Mobile Safari

3
DavidTaubmann

Vous devriez peut-être autoriser l'ouverture de liens dans une nouvelle fenêtre lorsque target est également défini explicitement sur "_blank":

$('a').live('click', function (event)
{      
    var href = $(this).attr("href");

    // prevent internal links (href.indexOf...) to open in safari if target
    // is not explicitly set_blank, doesn't break href="#" links
    if (href.indexOf(location.hostname) > -1 && href != "#" && $(this).attr("target") != "_blank")
    {
        event.preventDefault();
        window.location = href;
    }

});
3
daformat

Vous pouvez également faire des liens presque normalement:

<a href="#" onclick="window.location='URL_TO_GO';">TEXT OF THE LINK</a>

Et vous pouvez supprimer les balises hash et href, tout ce qu’il fait affecte l’apparence.

2
JuR

Ceci est une version légèrement adaptée de Sean qui empêchait le bouton retour

// this function makes anchor tags work properly on an iphone

$(document).ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
  // For iOS Apps
  $("a").on("click", function(e){

    var new_location = $(this).attr("href");
    if (new_location != undefined && new_location.substr(0, 1) != "#" && new_location!='' && $(this).attr("data-method") == undefined){
      e.preventDefault();
      window.location = new_location;
    }
  });
}

});

2
Richard Turner

C'est ce qui a fonctionné pour moi sur iOS 6 (très légère adaptation de la réponse de rmarscher):

<script>                                                                
    (function(document,navigator,standalone) {                          
        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;                         
                }                                                       
                if ("href" in curnode && (curnode.href.indexOf("http") || ~curnode.href.indexOf(location.Host)) && curnode.target == false) {
                    e.preventDefault();                                 
                    location.href=curnode.href                          
                }                                                       
            },false);                                                   
        }                                                               
    })(document,window.navigator,"standalone")                          
</script>
2
bjh

Une solution de contournement que j'ai utilisée pour une application Web iOS était d'avoir créé tous les liens (qui étaient des boutons avec CSS) sous la forme de boutons de soumission. Alors j'ai ouvert un formulaire qui a posté sur le lien de destination, puis une entrée type = "submit" Ce n'est pas la meilleure façon, mais c'est ce que j'ai découvert avant de trouver cette page.

1
dster77

J'ai créé un paquet installable bower à partir de réponse de @mmarscher qui peut être trouvé ici:

http://github.com/stylr/iosweblinks

Vous pouvez facilement installer le fragment avec bower en utilisant bower install --save iosweblinks

1
Robin van Baalen

Je préfère ouvrir tous les liens du mode d'application Web autonome, à l'exception de ceux qui ont target = "_ blank". Utiliser jQuery, bien sûr.

$(document).on('click', 'a', function(e) {
    if ($(this).attr('target') !== '_blank') {
        e.preventDefault();
        window.location = $(this).attr('href');
    }
});
1
Alex Haas

Pour ceux qui utilisent JQuery Mobile, les solutions ci-dessus ouvrent une boîte de dialogue contextuelle. Cela gardera les liens dans webapp et permettra des popups.

$(document).on('click','a', function (event) {
    if($(this).attr('href').indexOf('#') == 0) {
        return true;
    }
    event.preventDefault();
    window.location = $(this).attr('href');     
});

Pourrait aussi le faire par:

$(document).on('click','a', function (event){
    if($(this).attr('data-rel') == 'popup'){
        return true;
    }
    event.preventDefault();
    window.location = $(this).attr('href');     
});
1
Hexchaimen

Pour ceux avec Twitter Bootstrap et Rails 3

$('a').live('click', function (event) {
  if(!($(this).attr('data-method')=='delete')){
    var href = $(this).attr("href");
    event.preventDefault();
    window.location = href; 
  }   
});

Les liens de suppression fonctionnent toujours de cette façon.

1
wouf

Voici ce que je voudrais utiliser pour tous les liens sur une page ...

document.body.addEventListener(function(event) {
    if (event.target.href && event.target.target != "_blank") {
        event.preventDefault();
        window.location = this.href;                
    }
});

Si vous utilisez jQuery ou Zepto ...

$("body").on("click", "a", function(event) {
   event.target.target != "_blank" && (window.location = event.target.href);
});
0
alex