2010-01-09 6 views
3

Comment puis-je remplacer le texte sélectionné par un autre texte à l'aide de javascript PURE, dans Firefox?Remplacer le texte sélectionné dans Firefox

Ce que j'utilise pour obtenir la sélection:

var sel = this.getSelection(); 
var range = sel.getRangeAt(0); 

Et aussi cette importante question:
Je veux conserver le format des caractères d'origine (bien sûr la nouvelle chaîne aura le format)
La sélection peut être faite "cross-elements" (par ceci je veux dire que la sélection peut contenir du texte d'un élément comme div ou table et du texte d'un autre élément).

exemple, le document:

<div> 
this is a test 
</div> 
<div> 
<b>still a test</b> 
</div> 
<table style="width:100%;"> 
     <tr> 
      <td> 
       another word</td> 
      <td> 
       stackoverflow</td> 
     </tr> 
     <tr> 
      <td> 
       bump</td> 
      <td> 
       </td> 
     </tr> 
    </table> 

l'utilisateur de sélectionner le texte suivant (via une sélection):

son est un test encore anot test

Alors maintenant Je veux remplacer le texte en gardant le format, par exemple remplacer chaque chose par une nouvelle chaîne =

XXX XX X XXXX XXXX XXXX XXXXX X

Document final (remplacer après) sera:

<div> 
tXXX XX X XXXX 
</div> 
<div> 
<b>XXXXX X XXXX</b> 
</div> 
<table style="width:100%;"> 
     <tr> 
      <td> 
       XXXXher word</td> 
      <td> 
       stackoverflow</td> 
     </tr> 
     <tr> 
      <td> 
       bump</td> 
      <td> 
       </td> 
     </tr> 
    </table> 

Répondre

6

Wooove, qui était un peu dommage!

Javascript

var sel, range, nodevalue, startFound, stop; 

function goThroughElements(el){ 
    // If el is the start node, set startFound to true 
    if(el.isSameNode(range.startContainer)) startFound = true; 

    if(startFound){ 
     // If this is the start node, replace the text like this: abcd[ef gh] --> abcdxx xx 
     if(el.isSameNode(range.startContainer)){ 
      // \w stands for a word character 
      nodevalue = el.nodeValue.substring(range.startOffset).replace(/\w/g, 'x'); 
      el.nodeValue = el.nodeValue.substring(0, range.startOffset) + nodevalue; 

     } 

     // If this is the end node, replace the value like this: [abc def]gh ij -> xxx xxxgh ij 
     else if(el.isSameNode(range.endContainer)){ 
      nodevalue = el.nodeValue.substring(0,range.endOffset).replace(/\w/g, 'x'); 
      el.nodeValue = nodevalue + el.nodeValue.substring(range.endOffset); 

      // Now we can stop 
      stop = true; 
     } 

     // If this is just a text node, replace the value by xxxx 
     else if(el.nodeType == 3){ 
      el.nodeValue = el.nodeValue.replace(/\w/g, 'x') 
     } 
    } 

    // Loop trough el's brothers 
    while(el){ 
     // Stop if we need to 
     if(stop) return; 

     // If this element has child nodes, call this function again with the first child node 
     if(el.hasChildNodes()){ 
      goThroughElements(el.childNodes[0]); 
     } 

     // Jump to el's brother, or quit the loop 
     if(el.nextSibling) 
      el = el.nextSibling; 
     else 
      break; 
    } 

} 

$(document).ready(function() { 
    $(this).mouseup(function(){ 
     // Get the selection 
     sel = window.getSelection(); 
     range = sel.getRangeAt(0); 

     // Stop must be false if the last selected text node isn't found, startFound must be false when the start isn't found 
     stop = false; startFound = false; 

     if(range.collapsed == false){ 
      // Check if the selection takes place inside one text node element 
      if(range.startContainer.isSameNode(range.endContainer)){ 
       // ab[cdefg]h -> aaxxxxxh 
       nodevalue = range.startContainer.nodeValue; 
       range.startContainer.nodeValue = nodevalue.substring(0, range.startOffset) + nodevalue.substring(range.startOffset, range.endOffset).replace(/\w/g, 'x') + nodevalue.substring(range.endOffset); 
      } else {  
       // If the start node of the selection isn't the same as the end node, loop through all elements 
       goThroughElements(range.commonAncestorContainer.childNodes[0]); 
      } 
      // Collapse selection. 
      range.collapse(true); 
     }    
    }); 
}); 

Exemple

Vous pouvez try the code bien sûr

Peut-être pas la solution optimale, car il commence à rechercher le noeud de départ de la racine. Il serait plus rapide à la recherche du premier élément parent commun de range.startContainer et range.endContainer, mais je ne sais pas comment faire ...

Modifier

J'enveloppées les fonctions à l'intérieur-X if(range.collapsed == false) et utilisé range.commonAncestorContainer.childNodes[0] afin de commencer l'itération à travers les éléments du premier enfant du parent commun de la position de début et de fin de la sélection

+0

C'est super! pour l'élément parent, je pense que nous pouvons utiliser range.commonAncestorContainer, et pour vérifier les limites range.compareBoundaryPoints. S'il vous plaît voir si elle peut être utilisée pour votre code (je pense que ça peut), de toute façon, même si c'est j'accepterai votre réponse après votre commentaire :) merci – kenny

+0

Je pense que c'est range.comparePoint et pas range.compareBoundaryPoints – kenny

+0

Notez que cela ne fonctionne pas si le texte sélectionné est dans une zone de texte. Si c'est ce que vous voulez voir: http://stackoverflow.com/questions/4714192/insert-text-before-and-after-selection-in-textarea-with-javascript/4714850#4714850 –

Questions connexes