У меня есть следующий код:
<div class="TopMenu">
<h3>Create an Account</h3>
<h3>yup</h3>
<h3>lol</h3>
<a href="#">yo</a>
<ul>
<li sytle="display:">
<a href="#">start</a> or
<a href="#">finish</a>
</li>
</ul>
и я использую:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).text();
$(this).text(text.replace('or', 'triple'));
});
Он отлично работает, но ссылки не активны, как я могу это исправить?
Заранее большое спасибо.
Измените .text()
на .html()
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text.replace('or', 'triple'));
});
См. Скрипку
Здесь то, что ваш jQuery в основном переводится, когда он запускается:
text = this.textContent;
// text = "\n\t\tstart or\n\t\t finish\n\t\t\n";
text = text.replace('or','triple');
// text = "\n\t\tstart triple\n\t\t finish\n\t\t\n";
this.textContent = text;
// essentially, remove everything from 'this' and put a single text node there
Хорошо, это не большое объяснение XD. Дело в том, что установка textContent
(или, в jQuery, вызов .text()
) заменяет содержимое элемента этим текстом.
То, что вы хотите сделать, просто влияет на текстовые узлы. Я не знаю, как это сделать в jQuery, но здесь некоторые Vanilla JS:
function recurse(node) {
var nodes = node.childNodes, l = nodes.length, i;
for( i=0; i<l; i++) {
if( nodes[i].nodeType == 1) recurse(node);
else if( nodes[i].nodeType == 3) {
nodes[i].nodeValue = nodes[i].nodeValue.replace(/\bor\b/g,'triple');
}
}
}
recurse(document.querySelector(".TopMenu"));
Обратите внимание, что замена, основанная на регулярном выражении, не позволит "скучно" стать "btripleing". Используйте Vanilla JS и его магические способности, иначе я буду вас обманывать!
Это более сложная задача. Вам нужно заменить текст в текстовых узлах (nodeType === 3
), что может быть сделано с помощью contents()
и each
итерации:
$('.TopMenu li:contains("or")').contents().each(function() {
if (this.nodeType === 3) {
this.nodeValue = this.nodeValue.replace('or', 'triple');
}
});
Все остальные подходы будут либо переписывать разметку в элементе <li>
(удаление всех прикрепленных событий), либо просто удалить внутренние элементы.
Как обсуждалось в комментариях ниже, безупречным решением будет использование замены с регулярным выражением, то есть this.nodeValue.replace(/\bor\b/g, 'triple')
, который будет соответствовать всем or
как автономные слова, а не как части слов.
\bor\b
сделает работу в этом случае. Однако, если у ОП есть только текст or
там, неважно.
Вы должны нам .html()
вместо .text()
,
Как это:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text('or', 'triple'));
});
Вот живой пример: http://jsfiddle.net/7Mamj/
<a href="c-or-d.html">cake or death</a>
?
Так как or
является текстовым узлом, вы можете использовать .contents() вместе с .replaceWith():
$('.TopMenu li:contains("or")').each(function () {
var text = $(this).text();
$(this).contents().filter(function () {
return this.nodeType === 3 && $.trim(this.nodeValue).length;
}).replaceWith(' triple ');
});
Выполняя это, вы помещаете якоря в текст. Вы должны перебирать дочерние узлы с соответствующими элементами и использовать их только в свой textContent, чтобы не изменять любые теги или атрибуты html.
$('.TopMenu li:contains("or")').each(function() {
for(var i = 0; i < this.childNodes.length; i++){
if(this.childNodes[i].nodeName != "#text") continue;
this.childNodes[i].textContent = this.childNodes[i].textContent.replace(' or ', ' triple ');
}
});
<a href="c-or-d.html">cake or death?</a>
<a href="c-or-d.html">cake or death</a>