web-dev-qa-db-ja.com

リンクがjQuery / javascriptで外部にあるかどうかをテストしますか?

リンクが外部か内部かを確認するにはどうすればよいですか?ご注意ください:

  1. ローカルドメインをハードコーディングできません。
  2. 「http」をテストできません。 http絶対リンクを使用して自分のサイトに簡単にリンクできます。
  3. CSSではなくjQuery/javascriptを使用したい。

私は答えがlocation.hrefのどこかにあると思うが、解決策は私を回避する。

ありがとう!

60
Matrym
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"リンクも外部として一致します。いくつかの追加のRegExpチェックを行うことで改善される場合があります。


2016-11-17更新

この質問にはまだ多くのトラフィックがあり、多くの人から、この受け入れられた解決策は何度か失敗するだろうと言われました。私が述べたように、これはこの問題を解決する主な方法を示す非常に迅速で汚い答えでした。より洗練されたソリューションは、<a>(アンカー)要素でアクセス可能なプロパティを使用することです。この回答ですでに指摘されている@Davedのように、キーはhostnameを現在のwindow.location.hostnameと比較することです。 hostnameプロパティを比較したいのは、portプロパティに含まれているHostプロパティが80と異なる場合、それらが決して含まれないためです。

だからここに行きます:

$( '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' );
});
46
jAndy

この投稿は古いことは知っていますが、結果の一番上に表示されているので、別のアプローチを提供したいと思いました。アンカー要素のすべての正規表現チェックが表示されますが、なぜ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
    }
}
56
Daved

そして、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(http://、https://)で始まらないすべてのhrefは、自動的にローカルとして扱われます

37
Sean Kinsey
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.Host + ')');

使用法:

external.test('some url'); // => true or false
7
James

外部リンクのみの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/

7
Blazemonger

相対パスを使用するとどうなりますか。

例:/ 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(ローカルおよび外部)の問題もあります。しかし、その解決策はまだ見つかりませんでした。

is-url-external モジュールを使用できます。

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

これは、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}
1
fuuchi
/**
     * 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>
1
King Rayhan

この関数を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

興味のある人のために、要素がどのクラスを持ち、どのクラスがアタッチされるかを確認する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");

    });
});

Googleアナリティクスビットは無視できますが、リンクの種類がわかったので、ここでURLを使用したい場合があります。ターナリブロック内にコードを追加するだけです。 1つのタイプのリンクのみをチェックする場合は、代わりに3項をifステートメントに置き換えます。

出会った問題を追加するために編集しました。私のhrefの一部は「/ Courses /」のようでした。 hrefの最初と最後にスラッシュがあるかどうかをチェックするローカルページのチェックを行いました。ただし、開始時に「/」をチェックするだけで十分でしょう。

0

はい、location.hrefで現在のドメイン名を取得できると思います。もう1つの可能性は、リンク要素を作成し、srcを/に設定してから、標準URLを取得することです(これにより、ドメイン名ではなくベースURLを使用するとベースURLが取得されます)。

この投稿も参照してください: リンクのhrefプロパティから完全なURIを取得

0
Savageman