Условие замены текста на странице
Я работаю над простым плагином браузера, чтобы заменить одно слово другим, но с добавлением якоря для небольшой всплывающей подсказки. У меня это уже работает, но моя проблема в том, что если слово, которое нужно заменить, уже находится в якоре, то мой </a>
закрывает уже открытый <a>
,
Поэтому мне нужна помощь с тем, как заменить только слово, если оно не находится в открытом теге привязки. Следующим шагом является также убедиться, что целевое слово не находится в <input>
или другие неподходящие теги.
Мой код:
var regex = new RegExp("\\b" + nativeWord + "\\b", "igm");
var body = $('body');
body.each(function() {
$(this).html(
$(this).html().replace(regex, function() {
counter++;
if(counter > wordSwapLimit) {
return nativeWord;
} else {
return "<a class=\"tooltip\" href=\"#\">" + studyWord + "<span class=\"classic\">" + nativeWord + "</span></a>";
}
})
);
});
Я подозреваю, что мне может понадобиться написать более сложный RegExp, но это мой первый выход с ним, поэтому любые предложения будут с благодарностью!
Обновление Итак, у меня есть тестовая страница, с которой я работаю, чтобы посмотреть, как работает мой код. Это часть оригинального HTML-кода со страницы:
<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>
Но с кодом, показанным выше, и заменой 'chicken' на 'kip', это изменяется на:
<p id="changeArea"> I <a href="http://www.<a class=" tooltip"="">kip<span class="classic">chicken</span></a>.com">love <a class="tooltip" href="#">kip<span class="classic">chicken</span></a> but I hate beef. </p>
Если у меня нет якорей вокруг того, что я обмениваю, то это работает отлично, и я получаю хорошую подсказку при опрокидывании.
В очередной раз благодарим за помощь!
Обновление 2 По запросу, вот "необработанные" примеры, с которыми мой плагин может столкнуться при замене "курицы" на "kip":
<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>
<p id="changeArea2"> Chickenpie? pie-chicken. </p>
Я надеюсь на следующее:
<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>
<p id="changeArea2"> Chickenpie? pie-<a class="tooltip" href="#">kip<span class="classic">chicken</span></a>. </p>
Как вы можете видеть в первой строке, HTML-код оставлен один, как текст для слова, потому что он находится внутри URL-адреса, и поэтому его сломали бы, если бы был вставлен якорь моей подсказки. Вторая строка игнорирует "куриный пирог", потому что Я хочу только обмен слова целиком, в соответствии с моим существующим регулярным выражением. "пирог с курицей" все же поменяется местами. Эта строка обрабатывается правильно с существующим кодом.
Я буквально просто хочу добавить дополнительные правила к моему существующему коду, которые говорят: "Не заменяйте код и не заменяйте, если в открытом теге якоря".
1 ответ
Поскольку вы в JavaScript, у вас уже есть доступ к DOM. Почему вы пытаетесь использовать регулярные выражения???
Просто перебирайте текстовые узлы, игнорируя существующие ссылки:
(function(elem) {
var recurse = arguments.callee, nodes = elem.childNodes, l = nodes.length, i, t,
getLink = function() {
var a = document.createElement('a'), s = document.createElement('span');
a.href = "#";
a.className = "tooltip";
a.appendChild(document.createTextNode(studyWord));
s.className = "classic";
s.appendChild(document.createTextNode(nativeWord));
a.appendChild(s);
return a;
};
for( i=0; i<l; i++) {
switch(nodes[i].nodeType) {
case 1:
// element - recurse, but not if already a link
if( nodes[i].nodeName != "A") recurse(nodes[i]);
break;
case 3:
// text node, look for keyword
t = nodes[i].nodeValue.search(new RegExp("\\b"+nativeWord+"\\b","i"));
if( t > -1) {
// found it! now to hack around...
t = nodes[i].splitText(t);
t.splitText(nativeWord.length);
t.parentNode.replaceChild(t,getLink());
}
break;
}
}
})(document.body);
Обратите внимание: этот подход использует Vanilla JS. Это зависит от вас, чтобы убедиться, что он запускается после загрузки страницы. Это может быть сделано либо:
- Добавление
defer
приписать скрипт, если он внешний - Поместить сценарий прямо перед
</body>
(или, по крайней мере, после всего контента, на который вы хотите повлиять) - Заворачивая это в
window.onload
обработчик или даже$(function() {...})
так как вы уже используете JQuery.