2014-12-26 22 views
9

Ho un div contenteditableSostituire parola specifica in contenteditable

<div id="divTest" contenteditable="true"> 

ho bisogno di ottenere l'ultima parola dalla posizione del cursore e su certa condizione devo testare e rimuovere solo questa parola specifica. Qui di seguito è come sto facendo

$('#divTest').on('keyup focus', function (e) { 
      if (e.keyCode == 32) { 
       var lastWord = getWordPrecedingCaret(this),          spanLastWord = $('#lastWord'); 

      } 
     }); 

function getWordPrecedingCaret(containerEl) { 
       var preceding = "", 
            sel, 
            range, 
            precedingRange; 
       if (window.getSelection) { 
        sel = window.getSelection(); 
        if (sel.rangeCount > 0) { 
         range = sel.getRangeAt(0).cloneRange(); 
         range.collapse(true); 
         range.setStart(containerEl, 0); 
         preceding = range.toString(); 


        } 
       } else if ((sel = document.selection) && sel.type != "Control") { 
        range = sel.createRange(); 
        precedingRange = range.duplicate(); 
        precedingRange.moveToElementText(containerEl); 
        precedingRange.setEndPoint("EndToStart", range); 
        preceding = precedingRange.text; 
       } 

       var words = range.toString().trim().split(' '), 
         lastWord = words[words.length - 1]; 
        if (lastWord) { 

        var resultValue = 'some'; // this value is coming from some other function 
        if (resultValue == lastWord) { 
        alert('do nothing'); 
         // do nothing 
        } 
       else 
        { 
        alert('replace word'); 
        // delete That specific word and replace if with resultValue 
        } 
        return lastWord; 

       } 
      } 

Demo: http://codepen.io/anon/pen/ogzpXV

Ho cercato range.deleteContents(); ma quello cancellerà tutto il contenuto nel div. Come posso sostituire una parola specifica?

risposta

5

Per lavorare con Ranges dobbiamo tenere a mente che stiamo lavorando con i nodi, non solo il testo che viene reso. La struttura si desidera modificare è:

<div id="divTest" contenteditable="true"> <-- Element Node 
    "some text" <-- TextNode 
</div> 

Ma potrebbe anche essere:

<div id="divTest" contenteditable="true"> <-- Element Node 
    "some text" <-- TextNode 
    "more text" <-- TextNode 
    "" <-- TextNode 
</div> 

per risolvere il tuo problema è più semplice per gestire una sola TextNode, propongo di utilizzare la funzione normalize() di unirsi tutti di loro in uno solo.

Quindi è sufficiente impostare Range sui limiti della parola prima dello deleteContents(). Una volta eliminato, è possibile inserire un nuovo TextNode con la sostituzione utilizzando insertNode().

var wordStart = range.toString().lastIndexOf(lastWord); 
var wordEnd = wordStart + lastWord.length; 

/* containerEl.firstChild refers to the div's TextNode */     
range.setStart(containerEl.firstChild, wordStart); 
range.setEnd(containerEl.firstChild, wordEnd); 
range.deleteContents(); 
range.insertNode(document.createTextNode(resultValue)); 

Per far funzionare tutto questo, è necessario che il testo è in un unico TextNode. Ma dopo ìnsertNode il div conterrà più nodi di testo. Per risolvere questo problema è sufficiente chiamare normalize() per unire tutti gli elementi TextNode.

containerEl.normalize(); 

JSFiddle demo

+0

jsfiddle non sembra funzionare – Timmerz

+0

Ho aggiunto alcuni css per evidenziare il div editabile (era trasparente). Dovrebbe funzionare almeno in FF e Chrome. Grazie per il vostro feedback –

3
words = ['oele', 'geel', 'politie', 'foo bar']; 

function markWords() { 
    var html = div.html().replace(/<\/?strong>/gi, ''), 
     text = html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' '), 
     exp; 
    $.each(words, function(i, word) { 
     exp = new RegExp('\\b(' + word + ')\\b', 'gi'); 
     html = html.replace(exp, function(m) { 
console.log('WORD MATCH:', m); 
      return '<strong>' + m + '</strong>'; 
     }); 
    }); 
    //html = html.replace('&nbsp;', ' ').replace(/\s+/g, ' '); 
console.log('HTML:', html); 
console.log('----'); 
    div.html(html); 
} 

chiamare questa funzione su setinterval

Fiddle

+0

che sta per sostituire ogni parola all'interno della contenteditable con la parola sostitutiva, giusto? Diciamo, ho un testo come questo "Test one Test due Test | Three Test" Ora perché il mio cursore è prima di Tre quindi voglio sostituire solo quella parola di test. – Zerotoinfinity

Problemi correlati