除了特定的域名外,将所有外部链接在新标签页中打开

15

我正在尝试在一个新窗口中打开站点上的所有外部链接。但是在该站点上有两个版本,例如商店和主站点。因此,在主站点上,我们可能会有指向http://store.example.com的链接。

我已经有一些代码可以让我在一个新窗口中打开所有外部链接。但是我想排除某些域名,例如我上面提到的那个。

以下是代码:

$(document).ready(function() {
   $("a[href^=http]").each(function(){
      if(this.href.indexOf(location.hostname) == -1) {
         $(this).attr({
            target: "_blank",
            title: "Opens in a new window"
         });
      }
   })
});

我对JS / jQuery很陌生,因此任何额外的信息都将非常有帮助。

9个回答

18

为了通过编程方式触发点击事件,您可以这样做:

$(document).ready(function() {

   $("a[href^=http]").each(function(){

      // NEW - excluded domains list
      var excludes = [
         'excludeddomain1.com',
         'excludeddomain2.com',
         'excluded.subdomain.com'
      ];
      for(i=0; i<excludes.length; i++) {
         if(this.href.indexOf(excludes[i]) != -1) {
            return true; // continue each() with next link
         }
      }

      if(this.href.indexOf(location.hostname) == -1) {

           // attach a do-nothing event handler to ensure we can 'trigger' a click on this link
           $(this).click(function() { return true; }); 

           $(this).attr({
               target: "_blank",
               title: "Opens in a new window"
           });

           $(this).click(); // trigger it
      }
   })
});

技术方面,感谢您的回复。很抱歉,我没有看到这里有什么不同于页面顶部的内容。您能否告诉我在哪里添加域名,因为我认为它不会作为外部域名工作? - Josh Davies
请查看我的编辑,以获取排除列表逻辑(简单解决方案)。原始答案是为了指出如何在程序中触发链接点击(以便在新标签页中打开它们)。 - techfoobar
太棒了,谢谢。我已经将它实现到我的网站上了。只是在进行一些测试。当您指定域时,如果URL是“excludeddomain/somethingthatcanchangehere”,是否有影响?(希望这样说得清楚)。 - Josh Davies
那应该可以工作,你可能想要将其小写(以及排除数组的内容)以使其在所有情况下匹配。 - techfoobar
能否同时添加https和http? - Josh Davies
这个选择器匹配https,因为它以“http”开头。http://api.jquery.com/attribute-starts-with-selector/ - Dylan Valade

7
如果你只想获取不符合你的域名的所有链接:
var all_links = document.querySelectorAll('a');
for (var i = 0; i < all_links.length; i++){
       var a = all_links[i];
       if(a.hostname != location.hostname) {
               a.rel = 'noopener';
               a.target = '_blank';
       }
}

3
我很喜欢这个,因为它不需要 jQuery。 - Nico

1

抱歉打扰,我是通过谷歌搜索到这里的。我曾经遇到过类似的问题,最终是这样解决的:

document.body.addEventListener('click', function (e) {
  if (e.target.tagName !== 'A') return;
  if (e.target.hostname === location.hostname) return;
  if(['stackoverflow.com','someothersite.com'].indexOf(e.target.hostname) !== -1) return; 
  e.preventDefault();
  window.open(e.target.href);
  return false;
});

1

您能否编辑HTML以获得更好的钩子,例如单击事件?如果我需要将某些链接分为内部或外部链接,我会在HTML元素上应用rel值。

    <a href="URL" rel="external">Link</a>

然后在你的 JavaScript 中

    $('a[rel="external"]').click( function(event) {
     event.stopPropagation();
     window.open( $(this).attr('href') );
     return false;
    });

编辑:既然你已经有了大量的链接,那么这个怎么样?

    var a = new RegExp('http:\/\/store.blah.com');

    $('a').each(function() {

      if(a.test(this.href)) {
        $(this).click(function(event) {
         event.preventDefault();
         event.stopPropagation();
         window.open(this.href, '_blank');
        });
      }

    });

谢谢回复。是的,我可以访问HTML,但有数百个链接,你可以想象这需要一些时间。不过,我会记下你的方法,以备将来建站使用,所以感谢你。 - Josh Davies

0

我认为我会这样做:

    $(document).ready(function() {
      $("a[href^=http]").each(function(){
         if(this.href.indexOf(location.hostname) == -1 && this.href.indexOf("store.domain.com") == -1 && this.href.indexOf("other.domain.rule") == -1) {
            $(this).attr({
               target: "_blank",
               title: "Opens in a new window"
           });
         }
       })
    });

这种方法有点手动,但如果您不想处理字符串和数组的拆分,这是解决方案。我相信这会有所帮助。

编辑:除此之外,您还可以使用techfoobar的解决方案来触发链接点击。这将有助于提高您网站的性能。


非常好,非常感谢。看起来这对我很有用。我会尽快更新答案。 - Josh Davies

0

与techfoobar的回复类似,您可以构建一个域名列表,应该在同一窗口中保持打开。但是,您可以使用正则表达式以更强大的方式来执行此操作。如果您只是进行直接的indexOf()检查,则会跳过具有匹配子域但不匹配域的链接,尽管如果您想在href字符串中匹配名称,则可以省略'$'。

这个实现应该可以满足您的需求,并且对您需要的代码进行了最小的修改。

$(document).ready(function() {
    //populate this list with whatever domain names you want, the 
    //$ sign matches the end of the string, only top level domains are affected
    var whiteList = [/google.com\/$/, /stackoverflow.com\/$/];

   $("a[href^=http]").each(function(){
      if(this.href.indexOf(location.hostname) == -1) {

        //check if the href of the current link matches any of our patterns
        var href = this.href;
        if(whiteList.filter(function(x){return x.test(href)}).length == 0) {

         $(this).attr({
            target: "_blank",
            title: "Opens in a new window"
         });
        }
      }
   })
});

使用这个示例,所有链接到google.com和stackoverflow.com的链接也将在现有页面中打开。

0
如果您不想改变DOM,而是更愿意在body上使用事件处理程序,我建议使用类似以下的代码...
  // open external links in a new tab
  $('body').on('click','a',function(){
    var $a = $(this);
    var href = $a.attr('href');
    if (href.indexOf('/') == 0) return;  // ignore relative links
    var target = $a.attr('target') || "";
    if (target.length > 0) return; // ignore links with a target attribute already
    window.open(href, '_blank');  // open external links in a new tab
    return false;
  });

0

这将使用PHP为所有外部域名解决问题

$(document).ready(function() {
   $("a[href^=http]").each(function(){

      // NEW - excluded domains list
      var excludes = [
         '<?php echo $_SERVER['HTTP_HOST']; ?>'
      ];
      for(i=0; i<excludes.length; i++) {
         if(this.href.indexOf(excludes[i]) != -1) {
            return true; // continue each() with next link
         }
      }

      if(this.href.indexOf(location.hostname) == -1) {

           // attach a do-nothing event handler to ensure we can 'trigger' a click on this link
           $(this).click(function() { return true; }); 

           $(this).attr({
               target: "_blank",
               title: "Opens in a new window"
           });

           $(this).click(); // trigger it
      }
   })
});

只需将该php替换为location.hostname,您就不再需要php。 - Uberfuzzy

0

在 Collin 的原生 JS 答案的基础上进行改进,这非常好,因为它不需要 Jquery(尽管 OP 提出了问题)。但我会修改它,使其能够排除当前主机名以外的域名:

    var all_links = document.querySelectorAll('a');
    var excludes = ['domain1.com','www.domain1.com','domain2.com'];
    for (var i = 0; i < all_links.length; i++){
        var a = all_links[i];
        var found = false; 
        for(j=0; j<excludes.length; j++) {
                if(a.href.includes(excludes[j])) {
                    found = true;
                    break;  
                }
        }    
        if (!found) {
            a.rel = 'noopener'; a.target = 'external';
        }
    }        

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接