2017-05-05 64 views
6

假設我有以下HTML結構:替換元素含量,而無需更換HTML

<test> 
    <div> 
     This is a test 
     </div> 
    <div> 
     This is another test 
     <button> 
      Button test 
     </button> 
    </div> 
</test> 

現在我使用下面的jQuery代碼來代替,例如, 'T':

$("test *").each(function(index, value) { 
    $(this).html($(this).html().replace(new RegExp('t', "ig"), "<b>t</b>")); 
}); 

然而,這個結果在下面的HTML結構(這是意想不到的,看到<button>標籤,它打破我的HTML):

<test> 
    <div> 
     <b>T</b>his is a <b>t</b>es<b>t</b> 
     </div> 
    <div> 
     <b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b> 
     <bu<b>t</b><b>t</b>on> 
      Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b> 
      </bu<b>t</b><b>t</b>on> 
     </div> 
    </test> 

我想實現的是:

<test> 
    <div> 
     <b>T</b>his is a <b>t</b>es<b>t</b> 
     </div> 
    <div> 
     <b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b> 
     <button> 
      Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b> 
      </button> 
     </div> 
    </test> 

基本上,我想整個元素內更換,但保留了HTML代碼和所有的HTML屬性。

+1

所以,如果我理解正確的話,你不想

+0

@ Goose,正確,但這不僅適用於按鈕標籤,而且適用於當然與正則表達式匹配的所有html標籤。 –

回答

1

使用jQuery這可能是相當簡單的實現。創建一個函數,它接受你想要更新文本的元素,你想要替換的文本以及你想要替換的文本。然後,在要刪除子HTML的函數中,使用替換文本更新元素中剩下的任何文本。然後,您可以遞歸地爲每個子元素運行相同的函數,然後再將它們附加回父代。

function replaceTextInHtmlBlock($element, replaceText, replaceWith) 
 
{ 
 
    var $children = $element.children().detach(); 
 
    //Now that there should only be text nodes left do your replacement 
 
    $element.html($element.text().replace(replaceText, replaceWith)); 
 
    //Run this function for each child element 
 
    $children.each(function(index, me){ 
 
    replaceTextInHtmlBlock($(me), replaceText, replaceWith); 
 
    }); 
 
    $element.append($children); 
 
} 
 

 
$(document).ready(function(){ 
 
    $("#doReplace").click(function(){ 
 
    replaceTextInHtmlBlock($("#top"), $("#replace").val(), $("#with").val()); 
 
    }); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="top"> 
 
    <div> 
 
    This is a test 
 
    </div> 
 
    <div> 
 
    This is another test 
 
    <button> 
 
      Button test 
 
      </button> 
 
    </div> 
 
</div> 
 
<br /> 
 
<br /> 
 
<div> 
 
    <label>Replace</label> 
 
    <input id="replace" value="t" /> 
 
    <label>with</label> 
 
    <input id="with" value="<strong>t</strong>" /> 
 
    <button id="doReplace">Do Replace</button> 
 
</div>

+0

感謝您的回答,它似乎很好。 –

0

看起來你想大膽所有的T字符,但你的正則表達式也趕上你的HTML。

對innerText而不是innerHTML執行操作。我在幾年中沒有使用jQuery,所以可能會有更好的方法來做到這一點,但這應該做到這一點。

$("test *").each(function(index, value) { 
    $(this)[0].innerText = $(this)[0].innerText.replace(new RegExp('t', "ig"), "<b>t</b>"); 
}); 
+0

感謝您的回答,但是這會將所有兒童從父母權利中刪除?如果是這樣,那是不需要的行爲 –

+0

我剛剛測試過你的代碼,它根本不保存我的HTML。感謝您分享您的想法 –

+0

啊我明白你現在說的話。好吧,祝你好運! –

0

你能避免jQuery的,而不是擔心在講究button(因爲如果你打的input標籤等不會幫助),如果您在文本節點只能更換。

我們尋找文本節點,在每種情況下都找到我們看到的第一個「t」(或「T」),將它包裝在<b>中,然後繼續前進。稍後的文本節點中會找到同一區域中的其他匹配項。

var wrapText = "t"; 
 

 
var el = document.getElementsByTagName('test')[0]; 
 

 
replaceIn(el); 
 

 
function replaceIn(el) { 
 
    var i = 0; 
 

 
    while (i < el.childNodes.length) { 
 
    var cn = el.childNodes[i]; 
 

 
    if (cn.nodeType == 3) { // text node 
 
     var p = cn.textContent.toLowerCase().indexOf(wrapText); 
 

 
     if (p >= 0) { 
 
     var range = new Range(); 
 
     range.setStart(cn, p); 
 
     range.setEnd(cn, p + 1); 
 
     range.surroundContents(document.createElement('b')); 
 
     ++i; // don't check the <b> we just created 
 
     } 
 
    } 
 
    else { 
 
     replaceIn(cn); 
 
    } 
 

 
    ++i; 
 
    } 
 
}
<test> 
 
    <div> 
 
    This is a test 
 
    </div> 
 
    <div> 
 
    This is another test 
 
    <button> 
 
     Button test 
 
    </button> 
 

 
    <input value="input test" /> 
 
    </div> 
 
</test>

+0

感謝您的回覆。它效果很好,但是我必須處理一個非常慢的整個頁面。當我執行搜索時,網頁幾乎崩潰。 –

+0

如果您不想處理標籤,則必須處理單個文本節點而不是僅處理字符串。老實說,我認爲事後並不存在高性能的解決方案。 – Goose