使用 jQuery / javascript 测试链接是否是外部的?

发布于 2024-09-02 23:37:07 字数 219 浏览 7 评论 0原文

如何测试链接是外部链接还是内部链接?请注意:

  1. 我无法对本地域进行硬编码。
  2. 我无法测试“http”。我可以很容易地使用 http 绝对链接链接到我自己的网站。
  3. 我想使用 jQuery / javascript,而不是 css。

我怀疑答案就在 location.href 中的某个地方,但解决方案却回避了我。

谢谢!

How do I test to see if links are external or internal? Please note:

  1. I cannot hard code the local domain.
  2. I cannot test for "http". I could just as easily be linking to my own site with an http absolute link.
  3. I want to use jQuery / javascript, not css.

I suspect the answer lies somewhere in location.href, but the solution evades me.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

や莫失莫忘 2024-09-09 23:37:08

您可以使用 is-url-external 模块。

var isExternal = require('is-url-external');
isExternal('http://stackoverflow.com/questions/2910946'); // true | false 

You can use is-url-external module.

var isExternal = require('is-url-external');
isExternal('http://stackoverflow.com/questions/2910946'); // true | false 
戏蝶舞 2024-09-09 23:37:08
/**
     * All DOM url
     * [links description]
     * @type {[type]}
     */
    var links = document.querySelectorAll('a');
    /**
     * Home Page Url
     * [HomeUrl description]
     * @type {[type]}
     */
    var HomeUrl = 'https://stackoverflow.com/'; // Current Page url by-> window.location.href

    links.forEach(function(link) {
        link.addEventListener('click', function(e) {
            e.preventDefault();

            // Make lowercase of urls
            var url = link.href.toLowerCase();
            var isExternalLink = !url.includes(HomeUrl);

            // Check if external or internal
            if (isExternalLink) {
                if (confirm('it\'s an external link. Are you sure to go?')) {
                    window.location = link.href;
                }
            } else {
                window.location = link.href;
            }
        })
    })
<a href="https://stackoverflow.com/users/3705299/king-rayhan">Internal Link</a>
<a href="https://wordpress.stackexchange.com/">External Link</a>

/**
     * All DOM url
     * [links description]
     * @type {[type]}
     */
    var links = document.querySelectorAll('a');
    /**
     * Home Page Url
     * [HomeUrl description]
     * @type {[type]}
     */
    var HomeUrl = 'https://stackoverflow.com/'; // Current Page url by-> window.location.href

    links.forEach(function(link) {
        link.addEventListener('click', function(e) {
            e.preventDefault();

            // Make lowercase of urls
            var url = link.href.toLowerCase();
            var isExternalLink = !url.includes(HomeUrl);

            // Check if external or internal
            if (isExternalLink) {
                if (confirm('it\'s an external link. Are you sure to go?')) {
                    window.location = link.href;
                }
            } else {
                window.location = link.href;
            }
        })
    })
<a href="https://stackoverflow.com/users/3705299/king-rayhan">Internal Link</a>
<a href="https://wordpress.stackexchange.com/">External Link</a>

欲拥i 2024-09-09 23:37:08

这应该适用于除 IE 之外的每个浏览器上的任何类型的链接。

// check if link points outside of app - not working in IE
                try {
                    const href = $linkElement.attr('href'),
                        link = new URL(href, window.location);

                    if (window.location.host === link.host) {
                        // same app
                    } else {
                        // points outside
                    }
                } catch (e) { // in case IE happens}

This should work for any kind of link on every browser except IE.

// check if link points outside of app - not working in IE
                try {
                    const href = $linkElement.attr('href'),
                        link = new URL(href, window.location);

                    if (window.location.host === link.host) {
                        // same app
                    } else {
                        // points outside
                    }
                } catch (e) { // in case IE happens}
策马西风 2024-09-09 23:37:08

是的,我相信您可以使用 location.href 检索当前域名。另一种可能性是创建一个 link 元素,将 src 设置为 /,然后检索规范 URL(如果您使用的话,这将检索基本 URL,而不一定是域名)。

另请参阅这篇文章:获取完整的 URI链接的 href 属性

Yes, I believe you can retrieve the current domain name with location.href. Another possibility is to create a link element, set the src to / and then retrieving the canonical URL (this will retrieve the base URL if you use one, and not necessarily the domain name).

Also see this post: Get the full URI from the href property of a link

眼睛会笑 2024-09-09 23:37:08

对于那些感兴趣的人,我做了一个 if 块的三元版本,并检查该元素具有哪些类以及附加了哪些类。

$(document).ready(function () {
    $("a").click(function (e) {

        var hostname = new RegExp(location.host);
        var url = $(this).attr("href");

        hostname.test(url) ?
        $(this).addClass('local') :
        url.slice(0, 1) == "/" && url.slice(-1) == "/" ?
        $(this).addClass('localpage') :
        url.slice(0, 1) == "#" ?
        $(this).addClass('anchor') :
        $(this).addClass('external');

        var classes = $(this).attr("class");

        console.log("Link classes: " + classes);

        $(this).hasClass("external") ? googleAnalytics(url) :
        $(this).hasClass("anchor") ? console.log("Handle anchor") : console.log("Handle local");

    });
});

谷歌分析位可以被忽略,但既然你知道它是什么类型的链接,那么你可能想对这个 url 做一些事情。只需在三元块内添加代码即可。
如果您只想检查 1 种类型的链接,则将三元组替换为 if 语句。

编辑添加了我遇到的问题。我的一些 href 是“/Courses/”,如下所示。我检查了本地页面,检查 href 的开头和结尾是否有斜杠。尽管仅在开头检查“/”可能就足够了。

For those interested, I did a ternary version of the if block with a check to see what classes the element has and what class gets attached.

$(document).ready(function () {
    $("a").click(function (e) {

        var hostname = new RegExp(location.host);
        var url = $(this).attr("href");

        hostname.test(url) ?
        $(this).addClass('local') :
        url.slice(0, 1) == "/" && url.slice(-1) == "/" ?
        $(this).addClass('localpage') :
        url.slice(0, 1) == "#" ?
        $(this).addClass('anchor') :
        $(this).addClass('external');

        var classes = $(this).attr("class");

        console.log("Link classes: " + classes);

        $(this).hasClass("external") ? googleAnalytics(url) :
        $(this).hasClass("anchor") ? console.log("Handle anchor") : console.log("Handle local");

    });
});

The google analytics bit can be ignored but this is where you'd probably like to do something with the url now that you know what type of link it is. Just add code inside the ternary block.
If you only want to check 1 type of link then replace the ternaries with an if statement instead.

Edited to add in an issue I came across. Some of my hrefs were "/Courses/" like so. I did a check for a localpage which checks if there is a slash at the start and end of the href. Although just checking for a '/' at the start is probably sufficient.

冷情妓 2024-09-09 23:37:08

我将此函数用于 jQuery:

$.fn.isExternal = function() {
  var host = window.location.host;
  var link = $('<a>', {
    href: this.attr('href')
  })[0].hostname;
  return (link !== host);
};

用法是: $('a').isExternal();

示例: https://codepen.io/allurewebsolutions/pen/ygJPgV

I use this function for jQuery:

$.fn.isExternal = function() {
  var host = window.location.host;
  var link = $('<a>', {
    href: this.attr('href')
  })[0].hostname;
  return (link !== host);
};

Usage is: $('a').isExternal();

Example: https://codepen.io/allurewebsolutions/pen/ygJPgV

风月客 2024-09-09 23:37:08

这并不完全满足问题的“无法对我的域进行硬编码”的先决条件,但我发现这篇文章正在寻找类似的解决方案,就我而言,我可以对我的网址进行硬编码。我担心的是提醒用户他们正在离开网站,但如果他们留在网站上,则不会, 包括子域 (例如:blog.mysite.com,其中大多数其他答案都会失败)。这是我的解决方案,它从上面投票最高的答案中获取了一些内容:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
  a.classList.add( a.hostname.includes("mywebsite.com") ? 'local' : 'external' );
});

$("a").on("click", function(event) {
  if ($(this).hasClass('local')) {
    return;
  } else if ($(this).hasClass('external')) {
    if (!confirm("You are about leave the <My Website> website.")) {
      event.preventDefault();
    }
  }
});

This doesn't exactly meet the "cannot hardcode my domain" prerequisite of the question, but I found this post searching for a similar solution, and in my case I could hard code my url. My concern was alerting users that they are leaving the site, but not if they are staying on site, including subdomains (example: blog.mysite.com, which would fail in most of these other answers). So here is my solution, which takes some bits from the top voted answers above:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
  a.classList.add( a.hostname.includes("mywebsite.com") ? 'local' : 'external' );
});

$("a").on("click", function(event) {
  if ($(this).hasClass('local')) {
    return;
  } else if ($(this).hasClass('external')) {
    if (!confirm("You are about leave the <My Website> website.")) {
      event.preventDefault();
    }
  }
});
嘿哥们儿 2024-09-09 23:37:08

这对我有用:

function strip_scheme( url ) {
    return url.replace(/^(?:(?:f|ht)tp(?:s)?\:)?\/\/(www\.)?/g, '');
  }

  function is_link_external( elem ) {
    let domain = strip_scheme( elem.attr('href') );
    let host = strip_scheme( window.location.host );

    return ! domain.indexOf(host) == 0;
  }

this works for me:

function strip_scheme( url ) {
    return url.replace(/^(?:(?:f|ht)tp(?:s)?\:)?\/\/(www\.)?/g, '');
  }

  function is_link_external( elem ) {
    let domain = strip_scheme( elem.attr('href') );
    let host = strip_scheme( window.location.host );

    return ! domain.indexOf(host) == 0;
  }
梦太阳 2024-09-09 23:37:08

截至 2023 年,这样做对我来说已经完成了工作

export function isInternalLink(urlString: string): boolean | {
  pathname: string;
} {
  const url = new URL(urlString);
  if (url.origin !== window.location.origin) {
    return false;
  }
  return {
    pathname: url.pathname,
  };
}

As of 2023, doing this did the job for me

export function isInternalLink(urlString: string): boolean | {
  pathname: string;
} {
  const url = new URL(urlString);
  if (url.origin !== window.location.origin) {
    return false;
  }
  return {
    pathname: url.pathname,
  };
}

つ可否回来 2024-09-09 23:37:07

我知道这篇文章很旧,但它仍然显示在结果的顶部,所以我想提供另一种方法。我看到锚元素上的所有正则表达式检查,但为什么不只使用 window.location.host 并检查元素的 host 属性呢?

function link_is_external(link_element) {
    return (link_element.host !== window.location.host);
}

使用 jQuery:

$('a').each(function() {
    if (link_is_external(this)) {
        // External
    }
});

和使用纯 javascript:

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    if (link_is_external(links[i])) {
        // External
    }
}

I know this post is old but it still shows at the top of results so I wanted to offer another approach. I see all the regex checks on an anchor element, but why not just use window.location.host and check against the element's host property?

function link_is_external(link_element) {
    return (link_element.host !== window.location.host);
}

With jQuery:

$('a').each(function() {
    if (link_is_external(this)) {
        // External
    }
});

and with plain javascript:

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    if (link_is_external(links[i])) {
        // External
    }
}
⒈起吃苦の倖褔 2024-09-09 23:37:07
var comp = new RegExp(location.host);

$('a').each(function(){
   if(comp.test($(this).attr('href'))){
       // a link that contains the current host           
       $(this).addClass('local');
   }
   else{
       // a link that does not contain the current host
       $(this).addClass('external');
   }
});

注意:这只是一个快速的方法。肮脏的例子。它将匹配所有 href="#anchor" 链接
也作为外部。通过进行一些额外的正则表达式检查可能会得到改进。


更新2016-11-17

这个问题仍然有很多流量,很多人告诉我这个被接受的解决方案会多次失败。正如我所说,这是一个非常快速和肮脏的答案,展示了解决这个问题的主要方法。更复杂的解决方案是使用可在 (锚)元素上访问的属性。就像 @Daved 在这个答案中已经指出的那样,关键是将 hostname 与当前 window.location.hostname 进行比较。我更愿意比较 hostname 属性,因为它们从不包含 port,如果它不同于 80,则包含在 host 属性中。

所以我们开始:

$( 'a' ).each(function() {
  if( location.hostname === this.hostname || !this.hostname.length ) {
      $(this).addClass('local');
  } else {
      $(this).addClass('external');
  }
});

最先进的技术:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
    a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
var comp = new RegExp(location.host);

$('a').each(function(){
   if(comp.test($(this).attr('href'))){
       // a link that contains the current host           
       $(this).addClass('local');
   }
   else{
       // a link that does not contain the current host
       $(this).addClass('external');
   }
});

Note: this is just a quick & dirty example. It would match all href="#anchor" links
as external too. It might be improved by doing some extra RegExp checking.


Update 2016-11-17

This question still got a lot of traffic and I was told by a ton of people that this accepted solution will fail on several occasions. As I stated, this was a very quick and dirty answer to show the principal way how to solve this problem. A more sophisticated solution is to use the properties which are accessible on a <a> (anchor) element. Like @Daved already pointed out in this answer, the key is to compare the hostname with the current window.location.hostname. I would prefer to compare the hostname properties, because they never include the port which is included to the host property if it differs from 80.

So here we go:

$( 'a' ).each(function() {
  if( location.hostname === this.hostname || !this.hostname.length ) {
      $(this).addClass('local');
  } else {
      $(this).addClass('external');
  }
});

State of the art:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
    a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
挽清梦 2024-09-09 23:37:07

以及非 jQuery 方式

var nodes = document.getElementsByTagName("a"), i = nodes.length;
var regExp = new RegExp("//" + location.host + "($|/)");
while(i--){
    var href = nodes[i].href;
    var isLocal = (href.substring(0,4) === "http") ? regExp.test(href) : true;
    alert(href + " is " + (isLocal ? "local" : "not local"));
}

所有不以 http 开头的 href(http://、https://)都会自动视为本地

And the no-jQuery way

var nodes = document.getElementsByTagName("a"), i = nodes.length;
var regExp = new RegExp("//" + location.host + "($|/)");
while(i--){
    var href = nodes[i].href;
    var isLocal = (href.substring(0,4) === "http") ? regExp.test(href) : true;
    alert(href + " is " + (isLocal ? "local" : "not local"));
}

All hrefs not beginning with http (http://, https://) are automatically treated as local

半衾梦 2024-09-09 23:37:07
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');

用法:

external.test('some url'); // => true or false
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');

Usage:

external.test('some url'); // => true or false
欲拥i 2024-09-09 23:37:07

这是一个仅用于外部链接的 jQuery 选择器:

$('a[href^="(http:|https:)?//"])') 

仅用于内部链接(不包括同一页面内的哈希链接)的 jQuery 选择器需要稍微复杂一些:

$('a:not([href^="(http:|https:)?//"],[href^="#"],[href^="mailto:"])')

可以将其他过滤器放置在 :not() 条件并根据需要用附加逗号分隔。

http://jsfiddle.net/mblase75/Pavg2/


或者,我们可以使用 vanilla 过滤内部链接JavaScript href 属性,始终是绝对 URL:

$('a').filter( function(i,el) {
    return el.href.indexOf(location.protocol+'//'+location.hostname)===0;
})

http://jsfiddle.net/ mblase75/7z6EV/

Here's a jQuery selector for only external links:

$('a[href^="(http:|https:)?//"])') 

A jQuery selector only for internal links (not including hash links within the same page) needs to be a bit more complicated:

$('a:not([href^="(http:|https:)?//"],[href^="#"],[href^="mailto:"])')

Additional filters can be placed inside the :not() condition and separated by additional commas as needed.

http://jsfiddle.net/mblase75/Pavg2/


Alternatively, we can filter internal links using the vanilla JavaScript href property, which is always an absolute URL:

$('a').filter( function(i,el) {
    return el.href.indexOf(location.protocol+'//'+location.hostname)===0;
})

http://jsfiddle.net/mblase75/7z6EV/

电影里的梦 2024-09-09 23:37:07

你忘了一个,如果用相对路径怎么办。

例如:/test

        hostname = new RegExp(location.host);
            // Act on each link
            $('a').each(function(){

            // Store current link's url
            var url = $(this).attr("href");

            // Test if current host (domain) is in it
            if(hostname.test(url)){
               // If it's local...
               $(this).addClass('local');
            }
            else if(url.slice(0, 1) == "/"){
                $(this).addClass('local'); 
            }
            else if(url.slice(0, 1) == "#"){
                // It's an anchor link
                $(this).addClass('anchor'); 
            }
            else {
               // a link that does not contain the current host
               $(this).addClass('external');                        
            }
        });

还有文件下载.zip(本地和外部)的问题,可以使用“本地下载”或“外部下载”类。但还没有找到解决办法。

You forgot one, what if you use a relative path.

forexample: /test

        hostname = new RegExp(location.host);
            // Act on each link
            $('a').each(function(){

            // Store current link's url
            var url = $(this).attr("href");

            // Test if current host (domain) is in it
            if(hostname.test(url)){
               // If it's local...
               $(this).addClass('local');
            }
            else if(url.slice(0, 1) == "/"){
                $(this).addClass('local'); 
            }
            else if(url.slice(0, 1) == "#"){
                // It's an anchor link
                $(this).addClass('anchor'); 
            }
            else {
               // a link that does not contain the current host
               $(this).addClass('external');                        
            }
        });

There are also the issue of file downloads .zip (local en external) which could use the classes "local download" or "external download". But didn't found a solution for it yet.

水中月 2024-09-09 23:37:07
const isExternalLink = (url) => {
    const tmp = document.createElement('a');
    tmp.href = url;
    return tmp.host !== window.location.host;
};

// output: true
console.log(isExternalLink('https://foobar.com'));
console.log(isExternalLink('//foobar.com'));

// output: false
console.log(isExternalLink('https://www.stackoverflow.com'));
console.log(isExternalLink('//www.stackoverflow.com'));
console.log(isExternalLink('/foobar'));
console.log(isExternalLink('#foobar'));

使用这种方法的好处是:

  • 它会自动解析相对路径和片段的主机名
  • 它适用于protocol-relative URL

为了演示这一点,让我们看一下以下示例:

const lnk = document.createElement('a');
lnk.href = '/foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '#foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '//www.stackoverflow.com';

console.log(lnk.host); // output: 'www.stackoverflow.com'
const isExternalLink = (url) => {
    const tmp = document.createElement('a');
    tmp.href = url;
    return tmp.host !== window.location.host;
};

// output: true
console.log(isExternalLink('https://foobar.com'));
console.log(isExternalLink('//foobar.com'));

// output: false
console.log(isExternalLink('https://www.stackoverflow.com'));
console.log(isExternalLink('//www.stackoverflow.com'));
console.log(isExternalLink('/foobar'));
console.log(isExternalLink('#foobar'));

The benefit of using this approach is that:

  • It would automatically resolve the hostname for relative paths and fragments;
  • It works with protocol-relative URLs

To demonstrate this, let's look at the following examples:

const lnk = document.createElement('a');
lnk.href = '/foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '#foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '//www.stackoverflow.com';

console.log(lnk.host); // output: 'www.stackoverflow.com'
我爱人 2024-09-09 23:37:07

使用 jQuery

jQuery('a').each(function() {
    if (this.host !== window.location.host) {
        console.log(jQuery(this).attr('href'));
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

With jQuery

jQuery('a').each(function() {
    if (this.host !== window.location.host) {
        console.log(jQuery(this).attr('href'));
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文