使用 modernizr 确定是否支持多个 window 打开

using modernizr to determine if multiple window open is supported

这里记录了我遇到的问题。
window.open behaviour in chrome tabs/windows

您无法通过 javascript 在 chrome 中打开多个 windows。

如果支持,我想打开多个windows,如果不支持,我会简单地return一个链接列表。

有没有办法使用 modernizr 或除了浏览器嗅探之外的其他方法来确定是否支持该行为?

此功能可以在浏览器之间甚至通过浏览器配置打开多个 windows。 所以永远不要假设你将能够打开多个弹出窗口,你可能会,但你只能通过测试知道,它很容易测试。

要测试打开弹出窗口是否成功,请检查 return 值。

var popupWindow = window.open('http://www.google.com/');
if (!popupWindow) {
    console.log('the window did not open');
    // do other stuff
} 

如果 window 打开 return 值将是一个 Window 对象。 如果 window 没有打开,return 值将是假的,这个确切的 return 值可能因弹出窗口阻止程序而异,但通常您可以假设该值如果 window 没有打开,则为假;意思是 undefinednull.
因此,在 window 无法打开的情况下,很容易触发替代方法。

您不需要 modernizr 或任何插件,returning Window 对象的这种行为在所有浏览器中都是相同的。

MDN 参考:
https://developer.mozilla.org/en-US/docs/Web/API/Window/open

Firefox 和 Safari 似乎默认支持打开多个 windows。然而 Chrome 将阻止第二个 window 并显示 "pop up" 被阻止的小消息。 此外,Chrome 也将阻止并非来自直接用户操作的打开 windows;表示单击或按键。

像 modernizr 或任何自定义代码这样的东西不会为您提供任何类型的特征检测。主要原因是因为所有主流浏览器都需要某种用户操作才能以编程方式打开新的 window - 通常是单击。所以创建特征检测是不可能的。

这是一个有趣的问题,从 "progressive enhancement" 的角度思考可能会帮助您找到一个好的解决方案。

首先,假设您无法在 任何 浏览器中打开多个 windows。你会怎么做?按照您的建议显示 link 的列表。通过向每个 link 添加类似 target="_blank" 的东西,现在我们有一个没有任何 JavaScript 的工作应用程序(或者如果用户禁用了 JavaScript):

<section id="links-wrap">
  <a href="/page-A.html" target="_blank" />
  <a href="/page-B.html" target="_blank" />
</section>

此功能基线适用于有史以来的每一个浏览器 - 您的 Treo 访问者会爱上您。然而,这种体验并不理想,因为 link 很可能会打开新标签而不是新标签 windows。因此,让我们在单击 link 时使用 JavaScript 打开一个新的 window。我们还可以在单​​击后隐藏每个 link 并放置每个 window 以便它们不重叠:

function openWindowFromLink (link, idx) {
  var top = idx % 2 * 600;
  var left = Math.floor(idx/2) * 600;
  var win = window.open(link.href, 'Window '+ top +'x'+ left, 'width=600,height=600,top='+ top +',left='+ left);
  if (win) {
    link.style.display = "none";
  }
  return win;
}

function handleLinkClick(ev) {
  ev.preventDefault();
  var link = ev.target;
  var idx = 0;
  var prev = link.previousSibling;
  while (prev) {
    if (prev.nodeType === 1) {
        idx++;
    }
    prev = prev.previousSibling;
  }
  openWindowFromLink(link, idx);
}

document.getElementById('links-wrap').addEventListener('click', handleLinkClick);

困难的部分来了:我们如何一次打开多个 windows。正如我们所知,Chrome 每次用户点击只允许打开一个 window。虽然其他浏览器可能没有同样的限制,但他们可能会在将来添加它(我真的很惊讶他们现在 all 没有这个限制)。因此,让我们假设 所有 浏览器都具有与 Chrome 相同的限制。用户不想每次都单击每个 link - 所以让我们给他们一个单击目标,他们可以非常快速地单击以打开所有 windows。创造性的措辞将减少此任务的烦恼

<div id="rapid-click-box">
  Click me really fast and see what happens!
</div>

...还有一些 JavaScript:

var clickBox = document.getElementById('rapid-click-box');
var clickCount = 0;
clickBox.addEventListener('click', function handleRapidClick (ev) {
    var link = links[clickCount];
    if (link.style.display !== 'none') {
        openWindowFromLink(link, clickCount);
    }

    if (++clickCount === links.length) {
      clickBox.removeEventListener('click', handleRapidClick);
      clickBox.style.display = 'none';
    }
});

最后,让我们处理一下允许一次打开多个 windows 的浏览器。我们仍然需要用户点击才能调用 window.open - 所以让我们发挥创意,看看我们如何让用户点击某些东西。措辞巧妙的欢迎信息就足够了:

<div id="welcome-message" style="display:none">
  <h1>Hey, welcome to my site. Are you a human?</h1>
  <button>Yes</button>
</div>

<script>
// show the welcome message immediately if JS is enabled
document.getElementById('welcome-message').style.display = 'block';
</script>

... 再一次,一点 JavaScript:

var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function handleYesClick (ev) {
    ev.preventDefault();
    button.removeEventListener('click', handleYesClick);
    document.getElementById('welcome-message').style.display = 'none';

    for (var i = 0, l = links.length; i < l; i++) {
      if ( !openWindowFromLink(links[i], i) ) {
        break;
      }
    }

    if (i === links.length) {
      clickBox.style.display = 'none';
    }
});

还有一个 fiddle 来展示这一切:

https://jsfiddle.net/q8x5pqsw/