我希望将Safari中的新标签重定向到某个网址,实质上是更改默认的新标签页。但是,我不想重定向通过以下链接打开的新选项卡。
Windows and Tabs API描述标签“打开”事件,但是当任何新标签页打开时(包括从链接打开的新标签页),会触发这些事件。
有没有办法只为那些通过点击新标签按钮创建的标签捕获新的标签事件?
提前致谢!
答案 0 :(得分:7)
在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
。这意味着该选项卡将加载“热门站点”页面或“书签”页面(两个特殊的Safari页面,这些页面是新选项卡的选项之一)。就像一个空标签一样,这样的标签不可能是链接点击的结果,所以我们可以用标签做我们喜欢的事情。例如:
function handleBeforeNavigate(e) {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
if (e.url === null) {
takeOverTab();
}
}
案例3 :beforeNavigate
将触发,其url
值将为非空字符串:即实际网址。这是一个棘手的情况,因为选项卡可能来自链接点击,new-tab命令(如果用户已配置Safari以打开其主页的新选项卡),或另一个应用程序或扩展的操作。让我们调用选项卡是链接点击案例3A的结果的情况;案例3B,它是new-tab命令的结果;以及其他应用案例,案例3C。
我想不出区分3B和3C的方法。如果真的没有办法区分这两种情况,那么对你的应用来说可能非常糟糕,因为你可能不想重定向其他应用程序打开的标签。
如果您不关心您的应用是否会干扰3C标签,则至少有一种方法可以告知3B / 3C标签中的3A标签。这就是我的方式:
在每个页面中使用注入的脚本来侦听链接点击。单击链接时,将URL和点击时间转发到全局页面,这将记住它们以供将来参考。例如:
function handleMessage(e) {
if (e.name === 'linkClicked') {
lastClickedLinkUrl = e.message.url;
lastLinkClickTime = e.message.clickTime;
}
}
在beforeNavigate
处理程序中,测试事件的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();
}
}
请注意,此检测方法并非万无一失。可能有很多方法可能会出错。不过,我希望这会有所帮助。