Prueba si los enlaces son externos con jQuery / javascript?


¿Cómo pruebo para ver si los enlaces son externos o internos? Nota:

  1. No puedo codificar el dominio local.
  2. No puedo probar "http". Podría fácilmente estar enlazando a mi propio sitio con un enlace absoluto http.
  3. Quiero usar jQuery / javascript, no css.

Sospecho que la respuesta está en algún lugar.href, pero la solución me evade.

Gracias!

Author: Bhargav Rao, 2010-05-26

12 answers

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

Nota: este es solo un ejemplo rápido y sucio. Coincidiría con todos los enlaces href="#anchor" como externo también. Se podría mejorar haciendo un poco de comprobación RegExp adicional.


Actualización 2016-11-17

Esta pregunta todavía tiene mucho tráfico y un montón de gente me dijo que esta solución aceptada fallará en varias ocasiones. Como dije, esta fue una respuesta muy rápida y sucia para mostrar la forma principal de resolver este problema. Una más sofisticada la solución es usar las propiedades que son accesibles en un elemento <a> (ancla). Como @Daved ya señaló en esta respuesta, la clave es comparar el hostname con el actual window.location.hostname. Preferiría comparar las propiedades hostname, porque nunca incluyen la port que se incluye con la propiedad host si difiere de 80.

Así que aquí vamos:

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

Estado de la técnica:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
    a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
 40
Author: jAndy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-16 23:44:38

Sé que este post es viejo, pero todavía se muestra en la parte superior de los resultados, así que quería ofrecer otro enfoque. Veo todas las comprobaciones regex en un elemento anchor, pero ¿por qué no usar window.location.host y comprobar contra la propiedad host del elemento?

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

Con jQuery:

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

Y con javascript simple:

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    if (link_is_external(links[i])) {
        // External
    }
}
 51
Author: Daved,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-29 20:48:11

Y la forma de no-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"));
}

Todos los href que no comiencen con http (http://, https://) se tratan automáticamente como locales

 37
Author: Sean Kinsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-27 03:22:40
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');

Uso:

external.test('some url'); // => true or false
 7
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-26 08:28:14

Aquí hay un selector de jQuery solo para enlaces externos:

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

Un selector jQuery solo para enlaces internos (sin incluir enlaces hash dentro de la misma página) debe ser un poco más complicado:

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

Se pueden colocar filtros adicionales dentro de la condición :not() y separados por comas adicionales según sea necesario.

Http://jsfiddle.net/mblase75/Pavg2 /


Alternativamente, podemos filtrar enlaces internos usando la propiedad JavaScript de vainilla href, que es siempre una URL absoluta:

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

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

 7
Author: Blazemonger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-21 19:16:58

Olvidaste una, y si usas una ruta relativa.

Por ejemplo: / 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');                        
            }
        });

También existe el problema de las descargas de archivos .zip (local en external) que podría usar las clases "descarga local" o "descarga externa". Pero aún no encontré una solución.

 6
Author: Freelance webdesigner NL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 13:48:08

Puede usar el módulo is-url-external.

var isExternal = require('is-url-external');
isExternal('http://stackoverflow.com/questions/2910946'); // true | false 
 2
Author: mrded,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 14:32:55

/**
     * 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
Author: King Rayhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-17 10:20:31

Sí, creo que puede recuperar el nombre de dominio actual con la ubicación.href. Otra posibilidad es crear un elemento de enlace, establecer el src en / y luego recuperar la URL canónica (esto recuperará la URL base si usa una, y no necesariamente el nombre de dominio).

También vea este post: Obtenga el URI completo de la propiedad href de un enlace

 0
Author: Savageman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:57

Para aquellos interesados, hice una versión ternaria del bloque if con una comprobación para ver qué clases tiene el elemento y qué clase se adjunta.

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

    });
});

El bit de Google Analytics puede ser ignorado, pero aquí es donde probablemente te gustaría hacer algo con la url ahora que sabes qué tipo de enlace es. Simplemente agregue código dentro del bloque ternario. Si solo desea marcar 1 tipo de enlace, reemplace los ternarios con una instrucción if en su lugar.

Editado para añadir en un número que vine al otro lado. Algunos de mis href eran"/ Courses / " así. Hice una comprobación de una página local que comprueba si hay una barra al principio y al final de la href. Aunque simplemente comprobar si hay un ' / ' al principio es probablemente suficiente.

 0
Author: George F Delaney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-23 13:50:57

Uso esta función para jQuery:

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

El uso es: $('a').isExternal();

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

 0
Author: Allure Web Solutions,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-03 22:22:01

Esto debería funcionar para cualquier tipo de enlace en todos los navegadores excepto 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}
 0
Author: fuuchi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-02 12:52:33