Как автоматически добавить target= "blank" только во внешние ссылки?

Я создаю пользовательскую, отраслевую cms (используя django). В бэкэнде веб-мастера могут указать либо внутреннюю ссылку, например "/ page1", либо внешнюю ссылку для использования для различных элементов навигации по всему веб-сайту (все используют <a> при отображении) . Проблема в том, что я хотел бы открыть внутренние ссылки на текущей вкладке, но внешние ссылки должны использовать target="_blank" чтобы открыть новую вкладку или окно.

Как я могу обработать html для этого?

Я бы предпочел серверное решение, но не знаю никакого чистого способа предварительной обработки визуализированных шаблонов в django. Итак, я предполагаю, что самый простой способ сделать это, вероятно, решение javascript/jquery: скрипт, который запускается при загрузке каждой страницы, который добавляет атрибут target="_blank" ко всем внешним ссылкам, но не внутренним ссылкам. Но я не знаю, как это сделать.

7 ответов


Я использую следующие для awhile. Не могу вспомнить, где я нашел его первоначально:

$.expr[':'].external = function(obj){
    return !obj.href.match(/^mailto\:/)
           && (obj.hostname != location.hostname)
           && !obj.href.match(/^javascript\:/)
           && !obj.href.match(/^$/)
};

что добавляет :external селектор jQuery, поэтому вы можете просто сделать:

$('a:external').attr('target', '_blank');

хорошая часть об использовании пользовательского селектора заключается в том, что если вам нужно изменить то, что содержит "внешнюю" ссылку, вы можете изменить ее в одном месте и не беспокоиться об остальной части вашего кода. Например, в моей организации, у нас есть определенные поддомены, которые не являются "внешними", но что мы все еще хочу открыть в новых окнах.


попробуйте что-то вроде

for (var links = document.links, i = 0, a; a = links[i]; i++) {
        if (a.host !== location.host) {
                a.target = '_blank';
        }
}

Не забудьте запустить скрипт к тому времени, когда все ссылки существуют в дереве документов - в window.onload событие.


вы могли бы сделать что-то вроде этого:

$(document.body).on('mouseover', 'a[target!=_blank]:not(.local)', function (evt) {
    var a = $(this);
    var href = a.attr('href');
    var domain = href.match(/^https?:\/\/([^:\/]+)/);
    if (domain && domain[1] && domain[1] !== "yourdomain.com") {
        a.attr('target', '_blank');
    } else {
        a.addClass('local');
    }
});

Это будет обрабатывать каждую ссылку, как вы нажимаете на нее, и не должен обрабатывать каждую ссылку более одного раза. Если это должно быть внешним, то target будет установлен в _blank и он должен открыться в новом окне. вот рабочий jsfiddle.

обновление: мой метод определения, остается ли ссылка на месте или нет, довольно груб. Метод в ответ более тщательный. Я бы наверное, заменить мой простой матч regex с этот тест вместо.


Я рекомендую вам делать это на стороне сервера. Измените шаблон страницы в зависимости от местоположения ссылки.


вы также можете сделать это:

$("a[href^='http://']").attr("target","_blank");

или

$('a').each(function() {
   var a = new RegExp('/' + window.location.host + '/');
   if(!a.test(this.href)) {
       $(this).click(function(event) {
           event.preventDefault();
           event.stopPropagation();
           window.open(this.href, '_blank');
       });
   }
});

небольшое изменение кода, которое не дает ошибок, дополнительно = in != =

$.expr[':'].external = function(obj){
    return !obj.href.match(/^mailto\:/) && (obj.hostname !== location.hostname) && !obj.href.match(/^javascript\:/) && !obj.href.match(/^$/);
};
$('a:external').attr('target', '_blank');

другое решение JavaScript:

(() => {
  (document.querySelectorAll('a')).forEach(link => {
    link.hostname !== location.hostname && link.setAttribute('target', '_blank');
  })
})();