2010-05-26 12 views
50

¿Cómo puedo probar para ver si los enlaces son externos o internos? Tenga en cuenta:¿Prueba si los enlaces son externos con jQuery/javascript?

  1. No puedo codificar el dominio local.
  2. No puedo realizar la prueba de "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 de location.href, pero la solución me evade.

Gracias!

+0

quieres comprobarlo cuando se hace clic en el enlace o al cargar la página ? – Elangovan

+0

carga de la página, gracias. – Matrym

+1

Tu respuesta no funciona. Todas las comprobaciones deben hacerse en 'element.href' (desde DOM) en lugar de' $ (elemento) .attr ('href') '. Prueba: http://jsfiddle.net/rahzy/1/ Por favor, acepte la respuesta de Sean. – Nowaker

Respuesta

33
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: esto es sólo un ejemplo rápido & sucio. Igualaría todos los enlaces href = "# ancla" como externos también. Podría mejorarse haciendo alguna comprobación adicional de RegExp.


actualización 2016-11-17

Esta pregunta todavía tiene mucho tráfico y me dijeron que por un montón de gente 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 cómo resolver este problema. Una solución más sofisticada es usar las propiedades a las que se puede acceder en un elemento <a> (ancla). Al igual que @Daved ya se señaló en esta respuesta, la clave es comparar el hostname con el actual window.location.hostname. Yo preferiría para comparar las propiedades hostname, porque nunca incluyen el port que se incluye a 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 del arte:

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

Esto funciona bastante bien, aunque voy a aplazar una respuesta en caso de que alguien más tenga una solución más elegante. Por curiosidad, ¿por qué los enlaces de anclaje se registran como externos? – Matrym

+7

Estoy bastante seguro de que esto no funcionará con las URL relativas. 'attr' se supone que devuelve el atributo, no la propiedad (la propiedad podría resolverse, no el atributo). –

+10

http://jsfiddle.net/zuSeh/ Se verifica que este método no funciona para las URL relativas. –

0

Sí, creo que puede recuperar el nombre de dominio actual con location.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 ver este post: Get the full URI from the href property of a link

35

Y la forma 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 hrefs no comenzando con http (http: //, https: //) son tratados automáticamente como locales

+1

Esto se verifica por cierto –

+1

Esta respuesta es más precisa. Los parientes URL también son importantes. – Savageman

+0

Si no me equivoco, "($ | /" en realidad debería ser "($ | /)" con una llave de cierre –

6
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')'); 

Uso:

external.test('some url'); // => true or false 
+1

+1 para la expresión regular, aunque no resuelve completamente la pregunta – feeela

6

Se le olvidó uno, lo que si se utiliza un pariente camino.

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

Hay también el tema de las descargas de archivos .zip (local es externo) que podría utilizar las clases "descarga local" o "descarga externo". Pero aún no encontré una solución para eso.

+0

No todas las URL relativas comienzan con '/'. Puede hacer referencia a algo como 'images/logo.png', que es una carpeta hacia abajo desde su ubicación actual. En ese caso, está haciendo referencia a una ruta relativa en su URL relativa, tendrá un significado diferente en diferentes directorios de su sitio. '/ images/logo.png' es una ruta absoluta de cualquier sitio en el que se ejecuta (de ahí la relatividad). Su código no incluirá rutas relativas como 'images/logo.png'. –

48

Sé que esta publicación es antigua pero todavía se muestra en la parte superior de los resultados, así que quería ofrecer otro enfoque. Veo todas las verificaciones de expresiones regulares en un elemento delimitador, pero ¿por qué no simplemente usar window.location.host y verificar contra la propiedad del elemento host?

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 claro:

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

Esta es la única respuesta que tiene sentido para mí: las otras están muy desarrolladas. ¿Hay algún argumento en contra de este método? – tremby

+0

El jQuery anterior funciona para mí en Safari y maneja todos los problemas que manejan los demás: anclajes locales, URL relativas, URL de protocolo cruzado, etc. Nota: http://www.example.com y https:// www.example.com se marcará como interno; eso puede ser importante para ti. –

+1

Esta es la mejor respuesta. Esto hace uso del 'a.propiedad del host, que probablemente sea desconocida para el desarrollador promedio de JavaScript (incluyéndome a mí mismo antes de leer esto). – dana

7

es un selector de jQuery sólo para enlaces externos Aquí:

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

Un selector de jQuery sólo para enlaces internos (no inc. Luding enlaces de hash dentro de la misma página) tiene que ser un poco más complicado:

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

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

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


Alternativamente, podemos filtrar los enlaces internos utilizando el href propiedad vainilla JavaScript, 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/

+0

+1: OK, hubo una forma de volver a votar por esta respuesta :) –

+0

La primera no funciona como "// código .jquery.com/jquery.min.js "es una URL completamente legítima, pero no interna. El protocolo y los dos puntos no son necesarios, ya que el navegador utilizará lo que sea que esté usando el sitio actual (un protocolo semi-sorta relativo a la URL). – mikesir87

+1

@ mikesir87 Buen punto, actualizando. – Blazemonger

0

Para los interesados, que hizo una versión ternaria del bloque if con un control para ver qué clases tiene el elemento y qué clase s se apega.

$(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 análisis bits Google puede ser ignorado, pero esto es donde le apetezca hacer algo con la url ahora que ya sabe qué tipo de enlace que es. Solo agrega el código dentro del bloque ternario. Si solo quiere marcar 1 tipo de enlace, reemplace los ternarios con una declaración if en su lugar.

Editado para agregar un problema que encontré. Algunos de mis hrefs fueron "/ Courses /" como tal. Hice un control para una página local que verifica si hay una barra al principio y al final del href. Aunque basta con comprobar que hay un '/' al principio, probablemente sea suficiente.

1

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

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

puedo utilizar 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); 
}; 

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

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

Cuestiones relacionadas