如何仅将 target="_blank" 自动添加到外部链接?
Posted
技术标签:
【中文标题】如何仅将 target="_blank" 自动添加到外部链接?【英文标题】:How to automatically add target="_blank" to external links only? 【发布时间】:2012-08-16 00:51:16 【问题描述】:我正在构建一个自定义的、特定于行业的 cms(使用 django)。在后端,网站管理员可以指定一个内部链接,例如“/page1”或用于整个网站的各种导航元素的外部链接(渲染时都使用<a>
)。问题是我希望在当前选项卡中打开内部链接,但外部链接应该使用target="_blank"
打开新选项卡或窗口。
如何处理 html 以完成此操作?
我更喜欢服务器端解决方案,但我不知道在 django 中预处理渲染模板的任何干净方法。因此,我认为最直接的方法可能是 javascript/jquery 解决方案:在每个页面加载时运行的脚本,它将 target="_blank" 属性添加到所有外部链接而不是内部链接。但我也不知道该怎么做。
【问题讨论】:
我刚刚对其进行了编辑,以使以前(并且相当明显)隐含的问题明确。 id 使用中间件在服务器端执行此操作,该中间件解析响应并替换所需位置的代码。您可以使用 beautifulsoup 进行解析。 【参考方案1】:我建议你做那个服务器端。 根据链接的位置修改页面的模板。
【讨论】:
虽然我很欣赏你的观点,但我想我会等着看是否有人真的可以建议如何使用 django 在服务器端完成。【参考方案2】:试试类似的东西
for (var links = document.links, i = 0, a; a = links[i]; i++)
if (a.host !== location.host)
a.target = '_blank';
不要忘记在文档树中存在所有链接时运行脚本 - 在window.onload
事件中。
【讨论】:
我认为使用 jQuery 的 .ready() 代替 window.onload 会更合适,因为 .ready() 会在 DOM 完全加载后立即触发,而 window.onload 直到所有资源都不会触发已加载(图像等),这意味着用户有可能在添加目标之前点击。 @strille 这个问题没有被标记为 jQuery,所以我不想使用它,而且我不想让 OP 与DOMContentLoaded
+ 后备解决方案混淆,因为它不是跨浏览器的。但你是对的。
很抱歉忘记了最初的 jquery 标签。如果需要,请随时使用 jquery 修改答案。无论哪种方式,我都投了赞成票。【参考方案3】:
我一直在使用以下内容。不记得我最初在哪里找到的:
$.expr[':'].external = function(obj)
return !obj.href.match(/^mailto\:/)
&& (obj.hostname != location.hostname)
&& !obj.href.match(/^javascript\:/)
&& !obj.href.match(/^$/)
;
这增加了一个:external
jQuery 选择器,所以你可以这样做:
$('a:external').attr('target', '_blank');
使用自定义选择器的好处在于,如果您需要修改构成“外部”链接的内容,您可以在一处更改它,而不必担心其余代码。例如,在我的组织中,我们有某些不是“外部”的子域,但我们仍想在新窗口中打开。
【讨论】:
这很酷。我以前从未以这种方式扩展 jquery,但我喜欢简单的用法,以及您提到的优点。 这种确定主机名是在现场还是在现场外的方法非常好。比我的更彻底。 这太棒了。谢谢。 多年来我一直在生产中毫无问题地使用它,显然至少有 17 人认为它有效。它怎么不适合你?你有什么错误吗?【参考方案4】:你可以这样做:
$(document.body).on('mouseover', 'a[target!=_blank]:not(.local)', function (evt)
var a = $(this);
var href = a.attr('href');
var domain = href.match(/^https?:\/\/([^:\/]+)/);
if (domain && domain[1] && domain[1] !== "yourdomain.com")
a.attr('target', '_blank');
else
a.addClass('local');
);
这将在您单击每个链接时对其进行处理,并且不应多次处理每个链接。如果它需要是外部的,target
将被设置为_blank
,它应该在一个新窗口中打开。 Here's a working jsfiddle.
更新:我确定链接是否留在现场的方法非常粗略。 this answer中的方法比较彻底。我可能会用该测试替换我的简单正则表达式匹配。
【讨论】:
有趣的实时解决方案。 还没有完全工作。现在必须帮助面试,但稍后会回来编辑。 我想我更喜欢克里斯的回答,但我已经对你的回答投了赞成票。所以请随意清理它;只是想我会提醒你我可能会朝着不同的方向前进,所以不要着急。 他的回答很好。我能想到我的优势的唯一方法是您可以使用 javascript 动态添加链接,它们将自动工作,而无需您再次运行此代码。这就是.on
函数的美妙之处:)【参考方案5】:
你也可以这样做:
$("a[href^='http://']").attr("target","_blank");
或
$('a').each(function()
var a = new RegExp('/' + window.location.host + '/');
if(!a.test(this.href))
$(this).click(function(event)
event.preventDefault();
event.stopPropagation();
window.open(this.href, '_blank');
);
);
【讨论】:
【参考方案6】:代码稍有改动,不会报错,额外= in !==
$.expr[':'].external = function(obj)
return !obj.href.match(/^mailto\:/) && (obj.hostname !== location.hostname) && !obj.href.match(/^javascript\:/) && !obj.href.match(/^$/);
;
$('a:external').attr('target', '_blank');
【讨论】:
【参考方案7】:另一种 JavaScript 解决方案:
(() =>
(document.querySelectorAll('a')).forEach(link =>
link.hostname !== location.hostname && link.setAttribute('target', '_blank');
)
)();
【讨论】:
【参考方案8】:@Chris Pratt 的公认答案不适用于例如电话:链接和其他特殊情况我只是使用以下变体,以免触及特殊链接:
(function($)
$.expr[':'].external = function(obj)
return (obj.hostname != location.hostname) && obj.href.startsWith("http");
;
$('a:external').attr('target', '_blank');
) (jQuery);
【讨论】:
以上是关于如何仅将 target="_blank" 自动添加到外部链接?的主要内容,如果未能解决你的问题,请参考以下文章
Windows 8 应用 WebView 捕获事件 target="_blank"
我可以在 Markdown 中创建带有 'target="_blank"' 的链接吗?