2017-05-05 1 views
6

Supposons que je la structure HTML suivant:Remplacer le contenu dans des éléments sans remplacer HTML

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

Maintenant, j'utiliser le code jQuery suivant pour remplacer, par exemple, 'T':

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

Cependant, ce résultat dans la structure HTML suivant (ce qui est inattendu, voir l'étiquette <button>, qui brise le 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> 

Ce que je veux réaliser est:

<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> 

Fondamentalement, je veux remplacer dans l'élément entier, mais conserver les balises HTML et tous les attributs HTML.

+1

Donc, si je comprends bien, vous ne voulez pas

+0

@Goose, correct mais cela s'applique non seulement à la balise button, mais à toutes les balises html qui correspondent bien sûr à l'expression rationnelle. –

Répondre

1

Avec jQuery cela pourrait se faire assez simplement. Créez une fonction qui prend l'élément dont vous souhaitez mettre à jour le texte, le texte que vous souhaitez remplacer et ce que vous souhaitez le remplacer. Ensuite, dans la fonction, vous voulez supprimer le HTML enfant et mettre à jour tout texte laissé dans l'élément avec votre texte de remplacement. Vous pouvez ensuite exécuter récursivement cette même fonction pour chacun de vos éléments enfants avant de les réintégrer dans le parent.

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

Merci pour vos réponses, cela semble aller très bien. –

0

On dirait que vous voulez mettre en gras tous les caractères T, mais votre regex est également attraper votre code html.

Effectuez l'opération sur innerText plutôt que sur innerHTML. Je n'ai pas utilisé jQuery dans quelques années, donc il pourrait y avoir une façon plus optimale de le faire mais cela devrait le faire.

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

Merci pour votre réponse, mais cela va supprimer tous les enfants du parent droit? Si oui, c'est un comportement indésirable –

+0

Je viens de tester votre code, il ne conserve pas du tout mon code HTML. Merci d'avoir partagé vos pensées à ce sujet. –

+0

ahh Je vois ce que vous dites maintenant. Eh bien, bonne chance! –

0

Vous pouvez éviter jQuery, sans se soucier de button en particulier (car cela ne va pas aider si vous frappez une étiquette input, etc.), si vous remplacez seulement dans les nœuds de texte.

Nous recherchons des nœuds de texte, en repérant dans chaque cas le premier "t" (ou "T") que nous voyons, en l'enveloppant dans <b>, puis en continuant. D'autres correspondances dans la même zone seront trouvées dans des nœuds de texte plus récents.

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

Merci pour votre réponse. Cela fonctionne très bien, mais je dois traiter une page entière qui est terriblement lente. La page Web se bloque presque lorsque j'effectue la recherche. –

+0

Si vous ne souhaitez pas traiter les tags, vous devez traiter les nœuds de texte individuels au lieu de simplement la chaîne. Honnêtement, je ne pense pas qu'il existe une solution performante après le fait. – Goose