我希望将 Safari 中的新标签重定向到某个 URL,本质上是更改默认的新标签页。但是,我不想重定向通过以下链接打开的新选项卡。
Windows and Tabs API描述选项卡“打开”事件,但是当任何打开新选项卡(包括从链接打开的新选项卡)时会触发这些事件。
有没有办法只为那些通过单击新标签按钮创建的标签捕获新标签事件?
最佳答案
在您的open
事件处理程序中,首先检查事件目标是否为选项卡。如果是,请为该选项卡上的 beforeNavigate
事件注册一个事件处理程序。如果 beforeNavigate
事件没有在(比方说)50 毫秒内触发,还可以设置一个超时来注销处理程序。例如:
function handleOpen(e) {
if (e.target instanceof SafariBrowserTab) {
e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
setTimeout(function () {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
}, 50);
}
}
现在,标签页打开事件之后的 beforeNavigate
事件有三种相关的可能结果。
情况 1:beforeNavigate
事件不会在超时时间内触发。这通常意味着选项卡是空的。一个空标签不可能是点击链接的结果,所以我们可以在超时函数中放一些代码来做我们想做的事:
function handleOpen(e) {
if (e.target instanceof SafariBrowserTab) {
e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
setTimeout(function () {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
takeOverTab();
}, 50);
}
}
情况 2:beforeNavigate
事件将触发,其 url
属性的值为 null
.这意味着该选项卡将加载 Top Sites 页面或书签页面(两个特殊的 Safari 页面,它们是新选项卡的选项)。就像一个空标签一样,这样的标签不可能是点击链接的结果,所以我们可以对标签做我们喜欢的事情。例如:
function handleBeforeNavigate(e) {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
if (e.url === null) {
takeOverTab();
}
}
情况 3:beforeNavigate
将触发,其 url
值将是一个非空字符串:即,一个实际的 URL .这是一个棘手的案例,因为该选项卡可能是由链接单击、新选项卡命令(如果用户已将 Safari 配置为在其主页上打开新选项卡)或其他应用程序或扩展程序的操作引起的。我们将选项卡是链接点击结果的情况称为情况 3A;它是 new-tab 命令的结果的情况,情况 3B;和其他应用案例,案例 3C。
我想不出区分 3B 和 3C 的方法。如果真的没有办法区分这两种情况,则可能对您的应用非常不利,因为您可能不想重定向由其他应用打开的选项卡。
如果您不关心您的应用是否会干扰 3C 标签,至少有一种方法可以区分 3A 标签和 3B/3C 标签。这是我想到的方式:
在每个页面中使用注入(inject)脚本来监听链接点击。单击链接时,将 URL 和单击时间转发到全局页面,全局页面将记住它们以备将来引用。例如:
function handleMessage(e) { if (e.name === 'linkClicked') { lastClickedLinkUrl = e.message.url; lastLinkClickTime = e.message.clickTime; } }
在您的
beforeNavigate
处理程序中,测试事件的url
值是否与上次单击的链接的 URL 不同。如果是,则新选项卡不是由该链接点击产生的,因此它可能不是由任何链接点击产生的。如果这两个 URL 相同,请检查自上次链接点击后是否经过了超过 100 毫秒的时间。如果是这种情况,那么 URL 相同可能只是巧合,因此您可以再次推断新标签页不是由链接点击产生的。例如:function handleBeforeNavigate(e) { e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false); if (e.url === null) { takeOverTab(); } else if (e.url !== lastClickedLinkUrl || (new Date) - lastLinkClickTime > 100) { takeOverTab(); } }
请注意,这种检测方法并非万无一失。它可能有多种出错方式。不过,我希望这会有所帮助。
关于javascript - Safari 扩展 : Event for a completely new tab?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10148711/