Выбор XPath и управление DOM - PullRequest
       0

Выбор XPath и управление DOM

0 голосов
/ 12 сентября 2018

В этот ответ при работе со сценарием:

// This query finds all text nodes with at least 12 non-whitespace characters
// who are not direct children of an anchor tag
// Letting XPath apply basic filters dramatically reduces the number of elements
// you need to process (there are tons of short and/or pure whitespace text nodes
// in most DOMs)
var xpr = document.evaluate('descendant-or-self::text()[not(parent::A) and string-length(normalize-space(self::text())) >= 12]',
                            document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i=0, len=xpr.snapshotLength; i < len; ++i) {
    var txt = xpr.snapshotItem(i);
    // Splits with grouping to preserve the text split on
    var numbers = txt.data.split(/([(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4})/);
    // split will return at least three items on a hit, prefix, split match, and suffix
    if (numbers.length >= 3) {
        var parent = txt.parentNode; // Save parent before replacing child
        // Replace contents of parent with text before first number
        parent.textContent = numbers[0];

        // Now explicitly create pairs of anchors and following text nodes
        for (var j = 1; j < numbers.length; j += 2) {
            // Operate in pairs; odd index is phone number, even is 
            // text following that phone number
            var anc = document.createElement('a');
            anc.href = 'tel:' + numbers[j].replace(/\D+/g, '');
            anc.textContent = numbers[j];
            parent.appendChild(anc);
            parent.appendChild(document.createTextNode(numbers[j+1]));
        }
        parent.normalize(); // Normalize whitespace after rebuilding
    }
}

Я сталкиваюсь с проблемой, когда замена удаляет разметку, например <br> и <strong> и <a> и который удаляет текст и форматирование.Разметка выглядит следующим образом:

<strong>Location</strong><br />
Contact Name<br />
Contact Address<br />
City, State Zip<br />
P: (555) 555-5555<br /> 
F: (555) 555-5555 <br />
<a href="mailto:contact@domain.com">contact@domain.com</a><br />
Office Hours: M-F 8:30-12, 1-4

При запуске сценария я получаю замену P: <a href="tel:5555555555">(555) 555-5555</a>, но все остальное содержимое (местоположение, имя, адрес электронной почты и т. Д.) Удаляется.Если я уберу метки, замена будет работать только на номер телефона, как и предполагалось.Если я на правильном пути, я думаю, что проблема сводится к тому, как работает document.evaluate, только выбирая текстовые узлы.И appendChild только захватывает текст.Итак, как бы я изменил сценарий, чтобы сохранить разметку вокруг номера телефона.

Вот он в действии:

document.addEventListener("DOMContentLoaded", function() {
  // This query finds all text nodes with at least 12 non-whitespace characters
  // who are not direct children of an anchor tag
  // Letting XPath apply basic filters dramatically reduces the number of elements
  // you need to process (there are tons of short and/or pure whitespace text nodes
  // in most DOMs)
  var xpr = document.evaluate('descendant-or-self::text()[not(parent::A) and string-length(normalize-space(self::text())) >= 12]',
    document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  for (var i = 0, len = xpr.snapshotLength; i < len; ++i) {
    var txt = xpr.snapshotItem(i);
    // Splits with grouping to preserve the text split on
    var numbers = txt.data.split(/([(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4})/);
    // split will return at least three items on a hit, prefix, split match, and suffix
    if (numbers.length >= 3) {
      var parent = txt.parentNode; // Save parent before replacing child
      // Replace contents of parent with text before first number
      parent.textContent = numbers[0];

      // Now explicitly create pairs of anchors and following text nodes
      for (var j = 1; j < numbers.length; j += 2) {
        // Operate in pairs; odd index is phone number, even is 
        // text following that phone number
        var anc = document.createElement('a');
        anc.href = 'tel:' + numbers[j].replace(/\D+/g, '');
        anc.textContent = numbers[j];
        parent.appendChild(anc);
        parent.appendChild(document.createTextNode(numbers[j + 1]));
      }
      parent.normalize(); // Normalize whitespace after rebuilding
    }
  }
});
<strong>Location</strong><br /> Contact Name<br /> Contact Address<br /> City, State Zip<br /> P: (555) 555-5555<br /> F: (555) 555-5555 <br />
<a href="mailto:contact@domain.com">contact@domain.com</a><br /> Office Hours: M-F 8:30-12, 1-4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...