iPhone Safari Web App在新窗口中打开链接


155

将图标添加到主屏幕后,Web出现问题。如果从主屏幕启动网络,则所有链接将在Safari中的新窗口中打开(并失去全屏功能)。我该如何预防?我找不到任何帮助,只有一个未解决的问题。


3
您现在可以在scope中使用参数manifest.json。请参阅我的答案以获取更多详细信息。我已经在iOS 11.3中对其进行了测试,并且可以正常工作。
阿米尔·拉明法

3
重申一下,对于任何在iOS 11.3中无法打开Safari的人,请在此处查看@AmirRaminfar的答案:stackoverflow.com/a/49604315/32055
克里斯·海恩斯

Answers:


110

我在iWebKit框架中找到了JavaScript解决方案:

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

25
为了说明这一点并使之明确:iOS将Web Apps中的链接视为应在Safari中打开的链接,而javascript位置更改是允许在Web应用程序中满足的应用程序内操作。上面的代码之所以有效,是因为它阻止了默认的链接行为,将其替换为js nav调用。
奥斯卡·奥斯塔加德

6
有相反的例子吗?强制iPhone Web应用程序即使javascript位置更改也可以在Safari中打开页面?
tkahn 2012年

1
@Pavel感谢您提到iwebkit :)。有助于获得一些流量:D
cmplieger 2012年

3
[].forEach.call(document.links, function(link) { link.addEventListener("click", function(event) { event.preventDefault(); window.location = this.href; }) });
alex 2012年

1
这有副作用吗?
pingu 2013年

94

此处的其他解决方案要么不考虑外部链接(您可能想在Safari中从外部打开),要么不考虑相对链接(其中不包含域)。

html5 mobile-boilerplate项目链接到该要点,该要点对以下主题进行了很好的讨论:https : //gist.github.com/1042026

这是他们想出的最终代码:

<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>

除了一页,即我们公司的“与我们联系”页面之外,这非常有用。它没有显示页面,而是打开了应用程序“地图”并精确定位了我们的办公室。是什么原因造成的,我们如何解决?
乔纳森(Jonathan)

@乔纳森我不确定。如果删除此脚本,是否不会发生?也许发布一个链接到您的网站?或提出一个新问题,可能会更好。
rmarscher 2012年

@rmarscher这仅在运行您提供的代码时发生,而并非没有它。我本人是一名Web开发人员,我不明白为什么它会以这种方式处理链接。我没有页面网址,因为它当前未运行代码,因此您不会注意到它。而且,它不仅会影响独立的Safari,还会影响常规的Safari。感谢您的回答!
乔纳森(Jonathan)

这应该是可接受的答案,并且通过将代码放在标头中,可以在我用PHPRunner制作的iPad1全屏客户端上发挥作用。不知道为什么它会如此混乱,因为看起来相当简洁的代码可以在没有太多BW开销的情况下清晰地编写出来……虽然只是挑剔,但通常真的要说声谢谢。
sradforth

4
这会破坏Bootstrappy之类的东西,例如js函数使用的href =“#”链接
Sean

47

如果您使用的是jQuery,则可以执行以下操作:

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

1
请解释为什么.live()可能更好?
ajcw 2011年

8
live会将事件绑定到所有链接,包括尚不存在的链接,单击将仅绑定到当前存在的链接
msaspence 2011年

谢谢!救生员。我花了几个小时试图弄清楚为什么野生动物园一直都在加载。
史蒂夫

1
从我这里+1-用于this.href而不是强制转换为jQuery对象,但感谢您的回答。适用于iOS6。
Fenton 2012年

17
从jQuery 1.7开始不推荐使用 .live(),从1.9开始将其删除。使用$(document).on('click','a',function(){...})。
汤姆·戴维斯

21

这在iOS 6.1和Bootstrap JS链接(即下拉菜单等)上对我有效

$(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;
        }
      });
    }
  });

1
+1。实际上,这会在修复链接之前检查您是否正在使用Web应用程序。
小车

1
适用于iOS 8.0.2!谢谢
Joel Murphy

1
@sean我在iPad上运行了另一个webapp,该webapp使用图像地图作为href,此代码不起作用。对于所有其他链接都可以正常工作。有什么想法可以使此代码与图像映射一起使用吗?我尝试复制整个块并用$('a').on('click',function(e){` 替换function(e){` $('area').on('click',但这似乎也不起作用。有任何想法吗?
nematoth

如果您已经定义了click函数ahref="#"则可以在jquery选择器上进行更具体的说明,例如$('a[href!="#"]')
cjk

13

这是一个老问题,这里的许多解决方案都使用javascript。从那时起,iOS 11.3已发布,您现在可以使用scope成员。作用域成员是一个URL,就像该作用域"/"下的所有路径都不会打开新页面一样。

作用域成员是一个字符串,代表此Web应用程序的应用程序上下文的导航作用域。

这是我的示例:

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

您还可以在这里阅读更多有关它的信息。我还建议使用将提供此功能的生成器

如果您指定范围,则所有功能都将与Android一样,如预期般工作,超出范围的目的地将在Safari中打开-带有PWA后退按钮(状态栏中的小按钮)。


7
不幸的是,我认为您不能在范围内包括其他网站(例如其他域上的OAuth登录名)。
bhollis '18

嘿@Amir,我已经使用Angular创建了pwa,并且在Android上,我收到了“添加到主屏幕提示”,因为它看起来像是正确读取了manfest.json。但是,在IOs Chrome / Safari上,没有提示...任何想法吗?
乌斯塔德,

5

根据Davids的回答和Richards的评论,您应该执行域检查。否则,还将在您的Web应用程序中打开指向其他网站的链接。

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

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

以上解决方案的好补充。需要进行域检查,以防止人们在应用程序中打开外部网站。此外,可在iOS 5
Ian

我也可以在iOS 5上使用。有时问题可能出在缓存上。在测试不同方法时,我无法强迫iOS使其缓存无效并检索新版本的JS文件(Safari确实接受了更改,但将应用程序添加到主屏幕后没有更多更改)。更改我的开发服务器的端口很有帮助。如果您设置了max-age = 0(或等效值),那么这可能不会影响您。
Lukasz Korzybski 2012年

5

如果使用jQuery Mobile,则在使用data-ajax ='false'属性时会遇到新窗口。实际上,只要通过外部链接,通过$ .mobile.ajaxEnabled设置或具有target =“''属性关闭ajaxEnabled,就会发生这种情况。

您可以使用以下方法修复它:

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

(感谢Richard Poole的live()方法-不适用于bind())

如果已全局关闭ajaxEnabled,则需要删除[data-ajax ='false']。

我花了很长时间才弄清楚,因为我期望它是jQuery Mobile特有的问题,实际上实际上是Ajax链接实际上禁止了新窗口。


完美,您救了我:)
saulob 2014年

3

这段代码适用于iOS 5(对我有用):

在head标签中:

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

在要在同一窗口中打开的链接中:

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

我从以下评论中获得了这段代码:iphone web app meta标签


由于某些原因,我认为这是最容易理解的。
Jerrybibo'7

3

当目标也明确设置为“ _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;
    }

});

非常感谢!这是唯一适用于带Twitter Bootstrap的iOS5的代码。但是它不适用于生产。
Chim Kan

嗯,我不确定为什么它不能在生产中工作,但我认为这是另外一回事。让我知道!
daformat


2

您也可以几乎正常地进行链接:

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

并且您可以删除hash标签和href,它所做的一切都会影响外观。


2

这是在iOS 6上对我有用的功能(对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

这是对Sean的稍加改编的版本,该版本阻止了后退按钮

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

});


1

对于使用Twitter Bootstrap和Rails 3的用户

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

删除链接仍以这种方式工作。


1

我更喜欢在独立的Web应用程序模式下打开所有具有target =“ _ blank”的链接。当然,使用jQuery。

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

1

我用于iOS Web应用程序的一种解决方法是,我将所有链接(CSS的按钮)都设置为提交按钮。因此,我打开了一个表单,该表单发布到了目标链接,然后输入type =“ submit”并不是最好的方法,但这是我在找到此页面之前想出的。



1

对于使用的用户JQuery Mobile,上述解决方案将打破弹出对话框。这会将链接保留在webapp中,并允许弹出窗口。

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

也可以通过以下方式做到这一点:

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

0

这是我将用于页面上所有链接的内容...

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

如果您使用的是jQuery或Zepto ...

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

-3

您可以简单地删除此元标记。

<meta name="apple-mobile-web-app-capable" content="yes">
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.