2014-06-30 2 views
0

Я хотел бы заменить весь текст в каком-либо элементе (включая текст у детей) другим текстом. Так, например, HTMLУдалить текст из элемента без удаления ссылки

<div id="myText"> 
    This is some text. 
    This is some other text. 
    <p id="toHide"> 
     This is even more text. 
     Click this text to hide it. 
    </p> 
</div> 

должен стать

<div id="myText"> 
    That is some text. 
    That is some other text. 
    <p id="toHide"> 
     That is even more text. 
     Click That text to hide it. 
    </p> 
</div> 

По существу, я заменил все /this/gi с "That". Тем не менее, я не могу использовать следующее:

$("#myText").innerHTML = $("#myText").innerHTML.replace(/this/gi, ""); 

Это потому, что я держу много ссылок на детей myText. Эти ссылки будут удалены. Я понимаю, что в простых случаях я могу просто обновить эти ссылки, но у меня есть довольно большой файл и множество ссылок (и было бы неприятно и подвержено ошибкам обновлять каждую ссылку при каждом вызове этой функции).

Я также храню некоторые данные, которые не видны innerHTML. Например, я использую

$("#toHide").test = "test"; 

Это теряется при записи innerHTML.

Как заменить текст в div без innerHTML (желательно без jquery)?

Jsfiddlehttp://jsfiddle.net/prankol57/ZEfM7/

+0

@Oriol Я использую '$' в качестве ярлыка для 'document.querySelector' (см jsfiddle) – soktinpk

ответ

1

Вы можете использовать DOM методы (А.К.А. старым и безопасным способом)

function replaceText(el, pattern, txt) { 
    for(var i=0; i<el.childNodes.length; ++i) { 
     var node = el.childNodes[i]; 
     switch(node.nodeType){ 
      case 1: // Element 
       replaceText(node, pattern, txt); continue; 
      case 3: // Text node 
       node.nodeValue = node.nodeValue.replace(/this/gi, "that"); continue; 
     } 
    } 
} 

Demo

2

Вот решение:

var n, walker = document.createTreeWalker(document.getElementById("myText"), NodeFilter.SHOW_TEXT); 
while (n = walker.nextNode()) { 
    n.nodeValue = n.nodeValue.replace(/this/ig, "that"); 
} 

В принципе, пройдите все текстовые узлы и замените их значения.


Для лучшей совместимости, вот некоторые многоразовый код:

function visitTextNodes(el, callback) { 
    if (el.nodeType === 3) { 
     callback(el); 
    } 

    for (var i=0; i < el.childNodes.length; ++i) { 
     visitTextNodes(el.childNodes[i], callback); 
    } 
} 

Тогда вы можете сделать:

visitTextNodes(document.getElementById("myText"), function(el) { 
    el.nodeValue = el.nodeValue.replace(/this/ig, "that"); 
}); 
+0

документации для' createTreeWalker' кажется мало. Не могли бы вы объяснить, что он делает? (Я предполагаю, что это какой-то механизм фильтрации/итерации).Какова его поддержка в браузере? – soktinpk

+0

@soktinpk См. Статью [MDN article] (https://developer.mozilla.org/en-US/docs/Web/API/document.createTreeWalker), которая имеет [совместимость с браузером] (https: //developer.mozilla. org/en-US/docs/Web/API/document.createTreeWalker # Browser_compatibility). – Oriol

+0

Подумайте об этом как об итераторе по множеству фильтрованных узлов. Вы найдете совместимость браузеров на странице [этой страницы] (https://developer.mozilla.org/en-US/docs/Web/API/document.createTreeWalker). И вот [Документы для дерева TreeWalker] (https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker) –

1

Вот моя версия replaceText:

function replaceText(elem) { 
    if(elem.nodeType === Node.TEXT_NODE) { 
     elem.nodeValue = elem.nodeValue.replace(/this/gi, 'that') 
     return 
    } 
    var children = elem.childNodes 
    for(var i = 0, len = children.length; i < len; ++i) 
     replaceText(children[i]); 
} 

NB этот элемент принимает в качестве первого параметра и перемещает всех детей, поэтому он работает даже со сложными элементами.

Здесь обновленной скрипка: http://jsfiddle.net/ZEfM7/6/

+0

Я достаточно уверен, что мои элементы будут только на один уровень, но это хорошее решение для любого, у кого есть более сложный элемент. Так +1 в любом случае – soktinpk

Смежные вопросы