使用 JavaScript 检测在新窗口/标签(目标=_空白)中打开的功能

Posted

技术标签:

【中文标题】使用 JavaScript 检测在新窗口/标签(目标=_空白)中打开的功能【英文标题】:Feature detect opening in a new window/tab(target=_blank) with JavaScript 【发布时间】:2015-08-19 06:02:59 【问题描述】:

根据我的研究:

“WebView”可以禁用“在新窗口/选项卡中打开链接”。 原生应用开发者使用 WebView 在其应用中显示网页(请参阅 Twitter 的应用)。 通过用户代理检测 WebView 并不能始终如一地工作,也不是最佳做法。 简单地尝试用 JS 打开一个新窗口会触发弹出窗口拦截器;使其成为测试是否可以打开新窗口的不可靠方法。

我需要检测此功能何时不可用。不可能?

补充说明

我正在尝试检测是否可以通过 target=_blank 打开一个新窗口。例如,UIWebView [应用内浏览器] 可以阻止 target=_blank 按预期工作 [它只是在同一个窗口中打开而不是在新窗口中打开]。我需要一个解决方案来指示由于浏览器限制(例如 UIWebView 案例)而无法打开新窗口的时间。不幸的是,弹出窗口阻止程序阻止检查此类功能,因为它们不允许在没有用户输入(即单击)的情况下打开新窗口。

【问题讨论】:

那么,您是要检测 WebView,还是要弄清楚打开新窗口是否有效?或者你是否试图检测 WebView 假设打开一个新窗口永远不会与 WebView 一起工作(这是不正确的)? 事件监听器在事件发生后处理安全。所以你可以检测一个 webview,你可以检测用户代理,你甚至可以检查监听器或者查询 webview 的安全设置,但是你不能直接查询什么会被阻止。这不像库或 API 是否存在那么简单。 @DaveAlperovich 你不能检查一下<uses-permission android:name="android.permission.INTERNET" /> 吗? @maioman,是的,这是一种合法的检查方式。如果它是绝对的,我并不害怕,但这样的方法是正确的方法。 OP 似乎想要像if (window.allownew) 这样更具决定性的东西——“功能检查”,没有什么像这样的确定性 @BrianPetro 根据您的要求,我对其进行了测试。当它起作用时,我将其作为答案发布。如果您还需要什么,请告诉我。 【参考方案1】:

你不会有 100% 可靠的东西。

简单地尝试用 JS 打开一个新窗口会触发弹出窗口拦截器;使其成为测试是否可以打开新窗口的不可靠方法。

你是对的,它绝对不可靠...window.open() 被阻止(即使使用像 window.open(url, '_blank');window.focus(); 这样的技巧),click() 也被阻止(在包含 target="_blank" 的链接上),就像evt = document.createEvent("MouseEvents");evt.initEvent("click", true, true);...

但无论如何:如果 WebView 不允许在新选项卡中打开链接,那么它可以正常工作。但是正如您所暗示的那样,Webview 可能会对其进行授权。在这种情况下,您将不知道您是否在 web 视图中。很容易检测新选项卡中打开的链接是否最终以相同的方式打开(可以在未显示的 iframe 中用 javascript 测试),但如果链接是在浏览器中打开的,您无法知道(并想象一下使用 javascript 代码从应用程序在浏览器中打开一个新选项卡的用户体验......)。正如 Dave Alperovich 所说,如果不尝试,您无法提前知道什么会被阻止。所以你不应该往那边看。

没有可靠的功能或行为可以将 Webview 与 Web 浏览器区分开来。在 web 视图中,您拥有在浏览器中获得的所有内容(cookies、WebStorage ...)。用户代理有其缺陷,但它在许多情况下都可以工作。有解释here 或here 来构建它。

【讨论】:

已编辑以包含我能想到的最佳 UA 检测正则表达式。 /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)|(Android).*(wv|AppleWebKit.*Version)/i【参考方案2】:

根据 OP 请求,我已经对其进行了测试。它有效。如果启用了弹出窗口阻止程序,我将捕获它,因此我将获得一种可靠的方式来知道它已启用。在这种情况下,我只是发送警报,但您可以为所欲为。

代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Testing Pop-up Blocker</title>
<script>
function openPopUp(urlToOpen) 
  var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");            
  try 
    popup_window.focus();   
  
  catch (e) 
    alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
  

</script>
</head>
<body onload="openPopUp('http://www.google.com'); return false;">
<p>Testing Pop-up Blocker</p>
</body>
</html>

这就是我得到的,因为弹出窗口阻止程序已启用。

【讨论】:

我正在尝试检测是否可以打开一个新窗口,即使没有弹出窗口阻止程序。例如,UIWebView [in-app browser] 可以阻止 target=_blank 按预期工作[它只是在同一个窗口中打开而不是在新窗口中打开]。我需要此解决方案来指示由于浏览器限制(例如 UIWebView 案例)而无法打开新窗口的时间。不幸的是,弹出窗口阻止程序阻止检查此类功能,因为它们不允许在没有用户输入(即单击)的情况下打开新窗口。

以上是关于使用 JavaScript 检测在新窗口/标签(目标=_空白)中打开的功能的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 在新选项卡(而不是窗口)中打开 URL

使用 Capybara 在新窗口中打开链接

iPad Chrome - 在新窗口/选项卡中提交表单不起作用

通过javascript使用chrome中的新标签打开页面

什么时候应该在新标签/窗口中打开链接?

在新标签页中打开以进行打印