【问题标题】:How to automatically add target="_blank" to external links only?如何仅将 target="_blank" 自动添加到外部链接?
【发布时间】:2012-08-16 00:51:16
【问题描述】:

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

如何处理 html 以完成此操作?

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

【问题讨论】:

  • 我刚刚对其进行了编辑,以使以前(并且相当明显)隐含的问题明确。
  • id 使用中间件在服务器端执行此操作,该中间件解析响应并替换所需位置的代码。您可以使用 beautifulsoup 进行解析。

标签: javascript jquery django


【解决方案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);
        

        【讨论】:

          猜你喜欢
          • 2021-02-12
          • 1970-01-01
          • 2013-03-29
          • 2011-08-18
          • 1970-01-01
          • 2013-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多