12

我正在构建一个定制的、特定于行业的 cms(使用 django)。在后端,网站管理员可以指定一个内部链接,例如“/page1”或一个外部链接,用于整个网站的各种导航元素(全部<a>在呈现时使用)。问题是我希望在当前选项卡中打开内部链接,但应该使用外部链接target="_blank"打开新选项卡或窗口。

我怎样才能处理 html 来完成这个?

我更喜欢服务器端解决方案,但我不知道在 django 中预处理渲染模板的任何干净方法。因此,我认为最直接的方法可能是 javascript/jquery 解决方案:在每个页面加载时运行的脚本,它将 target="_blank" 属性添加到所有外部链接而不是内部链接。但我也不知道该怎么做。

4

8 回答 8

42

我一直在使用以下内容。不记得我最初在哪里找到它:

$.expr[':'].external = function(obj){
    return !obj.href.match(/^mailto\:/)
           && (obj.hostname != location.hostname)
           && !obj.href.match(/^javascript\:/)
           && !obj.href.match(/^$/)
};

这添加了一个:externaljQuery 选择器,所以你可以这样做:

$('a:external').attr('target', '_blank');

使用自定义选择器的好处在于,如果您需要修改构成“外部”链接的内容,您可以在一处更改它,而不必担心其余代码。例如,在我的组织中,我们有某些不是“外部”的子域,但我们仍想在新窗口中打开。

于 2012-08-20T17:24:18.703 回答
7

尝试类似的东西

for (var links = document.links, i = 0, a; a = links[i]; i++) {
        if (a.host !== location.host) {
                a.target = '_blank';
        }
}

不要忘记在文档树中存在所有链接时运行脚本 -window.onload以防万一。

于 2012-08-20T17:13:40.253 回答
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并且它应该在新窗口中打开。这是一个有效的 jsfiddle

更新:我确定链接是否留在现场的方法非常粗糙。这个答案中的方法更彻底。我可能会用该测试替换我的简单正则表达式匹配。

于 2012-08-20T17:25:22.400 回答
2

我建议你做那个服务器端。根据链接的位置修改页面的模板。

于 2012-08-20T17:09:37.793 回答
1

由于来自@Chris Pratt 的公认答案不适用于例如 tel: links 和其他特殊情况,我只使用以下变体以免触及特殊链接:

(function($) {

    $.expr[':'].external = function(obj){
        return (obj.hostname != location.hostname) && obj.href.startsWith("http");
    };

    $('a:external').attr('target', '_blank');

}) (jQuery);
于 2019-12-17T10:00:09.540 回答
0

你也可以这样做:

$("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');
       });
   }
});
于 2016-04-11T14:28:47.450 回答
0

代码略有变化,不会出错,在 !== 中附加 =

$.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');
于 2018-05-02T15:38:15.597 回答
0

另一个 JavaScript 解决方案:

(() => {
  (document.querySelectorAll('a')).forEach(link => {
    link.hostname !== location.hostname && link.setAttribute('target', '_blank');
  })
})();
于 2018-05-30T20:44:33.810 回答