Prueba si los enlaces son externos con jQuery / javascript?
¿Cómo pruebo para ver si los enlaces son externos o internos? Nota:
- No puedo codificar el dominio local.
- No puedo probar "http". Podría fácilmente estar enlazando a mi propio sitio con un enlace absoluto http.
- Quiero usar jQuery / javascript, no css.
Sospecho que la respuesta está en algún lugar.href, pero la solución me evade.
Gracias!
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' );
});
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
}
}
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
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
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;
})
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.
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
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>
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
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.
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();
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}
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