2012-06-03 48 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

您需要遞歸迭代文本節點,按空間chartacter分割文本節點值,然後用spans和新文本節點替換它。 – goat

+0

問題:你需要什麼來替換跨度爲? –

+0

@chris,你能舉個例子嗎? –

回答

1

實際使用DOM函數而不是使用regexp進行一些不可靠的字符串操作會更好。 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 ===

好的,第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

你是否可以將HTML變成一個'innertText'屬性? – Alnitak

+0

謝謝。但結果直接在網頁上顯示。 –