2012-06-03 2 views
2

Следующие коды не работают, и результат не работает, потому что в теге HTML есть пробелы.Javascript - Как заменить пробелы, которые не находятся в HTML-тегах?

HTML:

<div>Lorem ipsum <a id="demo" href="demo" rel="demo">dolor sit amet</a>, consectetur adipiscing elit.</div> 

Javascript:

var div = document.getElementsByTagName('div')[0]; 
div.innerHTML = div.innerHTML.replace(/\s/g, '<span class="space"> </span>'); 


Как заменить заменить пробелы, которые не в HTML-теги?

+1

Вам необходимо рекурсивно перебирать текстовые узлы, разделяя значения текстовых узлов на диаграмму пространства, а затем заменяя их на пробелы и новые текстовые узлы. – goat

+0

Вопрос: что вам нужно для замены пробелов? –

+0

@chris, не могли бы вы привести мне пример? –

ответ

1

Было бы лучше идею на самом деле использовать функции DOM, а не какие-то ненадежные манипуляции со строками, используя регулярное выражение. splitText - функция текстовых узлов, которая позволяет разделить текстовые узлы. Он пригодится здесь, поскольку он позволяет вам разбивать пространства и вставлять элемент <span> между ними. Вот демо-версия: http://jsfiddle.net/m5Qe8/2/.

var div = document.querySelector("div"); 

// generates a space span element 
function space() { 
    var elem = document.createElement("span"); 
    elem.className = "space"; 
    elem.textContent = " "; 
    return elem; 
} 

// this function iterates over all nodes, replacing spaces 
// with space span elements 
function replace(elem) { 
    for(var i = 0; i < elem.childNodes.length; i++) { 
     var node = elem.childNodes[i]; 
     if(node.nodeType === 1) { 
      // it's an element node, so call recursively 
      // (e.g. the <a> element) 
      replace(node); 
     } else { 
      var current = node; 
      var pos; 
      while(~(pos = current.nodeValue.indexOf(" "))) { 
       var next = current.splitText(pos + 1); 
       current.nodeValue = current.nodeValue.slice(0, -1); 
       current.parentNode.insertBefore(space(), next); 
       current = next; 
       i += 2; // childNodes is a live array-like object 
         // so it's necessary to advance the loop 
         // cursor as well 
      } 
     } 
    } 
} 
+0

Спасибо. Этот скрипт работает до сих пор. –

+0

В IE9 есть ошибка. Не могли бы вы взглянуть на него? –

+0

И когда тексты разбиваются на «перерыв строки + табуляция» вместо белых пространств, это кажется неработоспособным. –

0

Сначала разделите строку при каждом появлении > или <. Затем совмещаются все части в строку снова заменяя пробелы только в четных частей:

var div = document.getElementsByTagName('div')[0]; 
var parts = div.innerHTML.split(/[<>]/g); 
var newHtml = ''; 
for (var i = 0; i < parts.length; i++) { 
    newHtml += (i % 2 == 0 ? parts[i].replace(/\s/g, '<span class="space"> </span>') : '<' + parts[i] + '>'); 
} 
div.innerHTML = newHtml; 

this example Также см.

=== UPDATE ===

Ok, результат-го раскола IE может отличаться, то результат разделения всех остальных браузеров. При следующем обходного он должен работать:

var div = document.getElementsByTagName('div')[0]; 
var sHtml = ' ' + div.innerHTML; 
var sHtml = sHtml.replace(/\>\</g, '> <'); 
var parts = sHtml.split(/[<>]/g); 
var newHtml = ''; 
for (var i = 0; i < parts.length; i++) { 
    if (i == 0) { 
     parts[i] = parts[i].substr(1); 
    } 
    newHtml += (
     i % 2 == 0 ? 
     parts[i].replace(/\s/g, '<span class="space"> </span>') : 
     '<' + parts[i] + '>' 
    ); 
} 
div.innerHTML = newHtml; 

Также см this updated example.

=== UPDATE ===

Хорошо, я укомплектовать изменил мой сценарий. Он протестирован с IE8 и текущим firefox.

function parseNodes(oElement) { 
    for (var i = oElement.childNodes.length - 1; i >= 0; i--) { 
     var oCurrent = oElement.childNodes[i]; 
     if (oCurrent.nodeType != 3) { 
      parseNodes(oElement.childNodes[i]); 
     } else { 
      var sText = (typeof oCurrent.nodeValue != 'undefined' ? oCurrent.nodeValue : oCurrent.textContent); 
      var aParts = sText.split(/\s+/g); 
      for (var j = 0; j < aParts.length; j++) { 
       var oNew = document.createTextNode(aParts[j]); 
       oElement.insertBefore(oNew, oCurrent); 
       if (j < aParts.length - 1) { 
        var oSpan = document.createElement('span'); 
        oSpan.className = 'space'; 
        oElement.insertBefore(oSpan, oCurrent); 
        var oNew = document.createTextNode(' '); 
        oSpan.appendChild(oNew); 
       } 
      } 
      oElement.removeChild(oCurrent); 
     } 
    } 
} 

var div = document.getElementsByTagName('div')[0]; 
parseNodes(div); 

См. Также the new example.

+1

Если произвольный HTML является вопросом, регулярные выражения не являются ответом ... – Alnitak

+0

Спасибо. Однако IE7/8 имеет проблемы со следующим HTML:

Bla Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+0

И с этим тоже:

Lorem ipsum dolor sit amet, consectetur BlaBlaBla adipiscing elit.

0

Вы можете иметь дело с текстовым содержимым контейнера и игнорировать разметку.

var div = document.getElementsByTagName('div')[0]; 
if(div.textContent){ 
    div.textContent=div.textContent.replace(/(\s+)/g,'<span class="space"> </span>'; 
} 
else if(div.innerText){ 
    div.innerText=div.innerText.replace(/(\s+)/g,'<span class="space"> </span>'; 
} 
+0

вы _sure_ вы можете HTML в атрибут 'innertText'? – Alnitak

+0

Спасибо. Но результат показывает непосредственно на веб-странице. –

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