В этот ответ при работе со сценарием:
// 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