web-dev-qa-db-fra.com

Tester si les liens sont externes avec jQuery/javascript?

Comment puis-je tester pour voir si les liens sont externes ou internes? Notez s'il vous plaît:

  1. Je ne peux pas coder en dur le domaine local.
  2. Je ne peux pas tester pour "http". Je pourrais tout aussi facilement créer un lien vers mon propre site avec un lien absolu http.
  3. Je veux utiliser jQuery/javascript, pas css.

Je soupçonne que la réponse se trouve quelque part dans location.href, mais la solution m’échappe.

Merci!

57
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');
   }
});

Remarque: ceci est juste un exemple rapide et sale. Cela correspondrait à tous les liens href = "# anchor" as externes également. Il pourrait être amélioré en faisant une vérification supplémentaire de RegExp.


Mise à jour 2016-11-17

Cette question suscitait encore beaucoup de trafic et beaucoup de gens m'ont dit que cette solution acceptée échouerait à plusieurs reprises. Comme je l’ai dit, c’était une réponse très rapide et sale qui montrait le principal moyen de résoudre ce problème. Une solution plus sophistiquée consiste à utiliser les propriétés accessibles sur un élément <a> (ancre). Comme @Daved déjà souligné dans cette réponse, la clé est de comparer la hostname avec le window.location.hostname actuel. Je préférerais comparer les propriétés hostname, car elles n'incluent jamais la port qui est incluse dans la propriété Host si elle diffère de 80.

Alors on y va:

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

L'état de l'art:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
    a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
40
jAndy

Je sais que cet article est vieux mais il reste visible au sommet des résultats, alors je voulais proposer une autre approche. Je vois toutes les vérifications sur les expressions rationnelles sur un élément d'ancrage, mais pourquoi ne pas simplement utiliser window.location.Host et vérifier la propriété Host de l'élément?

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

Avec jQuery:

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

et avec javascript simple:

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

Et la manière non-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"));
}

Tous les hrefs ne commençant pas par http (http: //, https: //) sont automatiquement traités comme locaux. 

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

Usage:

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

Voici un sélecteur jQuery pour les liens externes uniquement:

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

Un sélecteur jQuery réservé aux liens internes (sans inclure les liens de hachage dans la même page) doit être un peu plus compliqué:

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

Des filtres supplémentaires peuvent être placés dans la condition :not() et séparés par des virgules si nécessaire.

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


Alternativement, nous pouvons filtrer les liens internes à l'aide de la propriété Vanilla JavaScript href, qui est toujours une URL absolue:

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

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

7
Blazemonger

Vous en avez oublié un, et si vous utilisiez un chemin relatif.

par exemple:/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');                        
            }
        });

Il existe également la question des téléchargements de fichiers .Zip (local et externe) qui pourrait utiliser les classes "téléchargement local" ou "téléchargement externe". Mais nous n'avons pas encore trouvé de solution.

Cela devrait fonctionner pour tout type de lien sur tous les navigateurs sauf 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}
2
fuuchi

Vous pouvez utiliser is-url-external module.

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

/**
     * 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

J'utilise cette fonction pour jQuery:

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

L'utilisation est: $('a').isExternal();

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

0

Pour les personnes intéressées, j’ai réalisé une version ternaire du bloc if avec un contrôle pour déterminer les classes de l’élément et celles qui sont attachées.

$(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");

    });
});

Le bit Google Analytics peut être ignoré, mais c’est là que vous voudriez probablement faire quelque chose avec l’URL maintenant que vous savez quel type de lien c’est. Ajoutez simplement du code dans le bloc ternaire . Si vous voulez seulement cocher 1 type de lien, remplacez les ternaires par une instruction if.

Édité pour ajouter un problème que j'ai rencontré. Certains de mes hrefs étaient "/ Courses /" comme ça. J'ai fait un chèque pour une page locale qui vérifie s'il y a une barre oblique au début et à la fin du href. Bien que vérifier le '/' au début soit probablement suffisant.

0
George F Delaney

Oui, je pense que vous pouvez récupérer le nom de domaine actuel avec location.href. Une autre possibilité consiste à créer un élément de lien, à définir le src sur/puis à récupérer l'URL canonique (l'URL de base sera récupérée si vous en utilisez un et pas nécessairement le nom de domaine).

Voir aussi ce post: Obtenir l'URI complet de la propriété href d'un lien

0
Savageman