Добавьте rel = "noopener", когда код загружен с помощью AJAX - PullRequest
0 голосов
/ 02 марта 2019


Я создал быстрый и простой скрипт для расширения chrome, чтобы добавить rel="noopener noreferrer" ко всем ссылкам с target="_blank" на веб-сайте.
Теперь дело обстоит так (например, на Tumblr, если вы прокручиваетеваш канал), если содержимое загружается во время просмотра на веб-сайте, сценарий, очевидно, не добавит noopener к ссылке.
Теперь я подумал об использовании MutationObserver , но если я изменю ссылки с помощью своего сценария, MutationObserver будеточевидно, что это изменение распознается, и я получу бесконечный цикл.

function gatherlinks() {
    var input = document.querySelectorAll('a[target="_blank"]');

    input.forEach(function addrelnoopener(link) {
        if (link.rel != 'noopener' || addrelnoopener.rel != 'noreferrer') {
            link.rel = 'noopener noreferrer';
        }
    });
}

У кого-нибудь есть мысли о том, как я могу обнаружить новые ссылки?

1 Ответ

0 голосов
/ 02 марта 2019

rel может иметь несколько значений, разделенных пробелами, которые вы не хотите перезаписывать (см. список ).

Используйте relList интерфейс DOM дляатрибут rel для добавления только отсутствующих значений, поэтому, когда MutationObserver сработает, он просто пропустит эти ссылки и не перейдет в бесконечный цикл:

// process the current document
onMutation([{
  addedNodes: [document.body],
}]);

// process the future modifications
const mo = new MutationObserver(onMutation);
mo.observe(document, {subtree: true, childList: true});

function onMutation(mutations) {
  var links = [];
  // ES5 loops with vars are still much faster in 2019,
  // which is important for subtree:true, more info: https://stackoverflow.com/a/39332340
  for (var i = 0; i < mutations.length; i++) {
    var addedNodes = mutations[i].addedNodes; 
    for (var j = 0; j < addedNodes.length; j++) {
      var node = addedNodes[j];
      if (node.tagName === 'A' && node.target === '_blank') {
        links.push(node);
      } else if (node.firstElementChild && node.querySelector('a[target*="_blank"]')) {
        links.push(...node.querySelectorAll('a[target*="_blank"]'));
      }
    }
  }

  for (var k = 0; k < links.length; k++) {
    var link = links[k];
    if (!link.relList.contains('noopener')) {
      link.relList.add('noopener');
    }
    if (!link.relList.contains('noreferrer')) {
      link.relList.add('noreferrer');
    }
  }
}

Или вы можете присоединить глобальный mousedown обработчик на window и измените по нажатой ссылке:

window.addEventListener('mousedown', e => {
  const link = e.target.closest('a');
  if (link) {
    const {relList} = link;
    if (!relList.contains('noopener')) {
      relList.add('noopener');
    }
    if (!relList.contains('noreferrer')) {
      relList.add('noreferrer');
    }
  }
}, true);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...