J’ai un div contenteditable
Je dois obtenir le dernier mot de la position du curseur et, à certaines conditions, je dois tester et supprimer ce mot uniquement. Voici comment je vais
$('#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.toSsortingng(); } } 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.toSsortingng().sortingm().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; } }
Démo: http://codepen.io/anon/pen/ogzpXV
J’ai essayé range.deleteContents (); mais cela supprimera tout le contenu de la div. Comment puis-je remplacer un mot spécifique uniquement?
- Convertir du HTML en texte brut dans contentEditable
- retourner le focus à contenteditable après execCommand?
- Evénements Contentés – Jquery
- ContentEditable div – tout le HTML après les premiers «x» caractères
- Comment placer le curseur à la fin du texte après avoir remplacé HTML par jQuery?
- contenteditable sur le double clic
- Récupère la position du curseur dans une div contenteditable
- Évitez la fonction createElement si elle se trouve dans un élément (contentEditable)
- Ne perdez pas le focus lorsque vous cliquez sur un autre élément
- selectionStart et selectionEnd dans l’élément contenteditable
Pour travailler avec les Ranges
nous devons garder à l’esprit que nous travaillons avec des nœuds, pas seulement le texte qui est rendu. La structure que vous souhaitez manipuler est la suivante:
<-- Element Node "some text" <-- TextNode
Mais cela pourrait aussi être:
<-- Element Node "some text" <-- TextNode "more text" <-- TextNode "" <-- TextNode
Pour résoudre votre problème, il est plus simple de gérer un seul TextNode
. Je propose d’utiliser la fonction normalize()
pour les associer à un seul.
Ensuite, il vous suffit de définir la Range
sur les limites du mot avant deleteContents()
. Une fois supprimé, vous pouvez insérer un nouveau TextNode
avec la substitution en utilisant insertNode()
.
var wordStart = range.toSsortingng().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));
Pour que cela fonctionne, il faut que le texte soit dans un seul TextNode
. Mais après ” ìnsertNode
le div
contiendra plusieurs nœuds de texte. Pour résoudre ce problème, appelez simplement normalize()
pour joindre tous les éléments TextNode
.
containerEl.normalize();
Modifier:
Comme le souligne Basj, la solution d’origine échoue pour plusieurs lignes. En effet, lorsque vous appuyez sur ENTER, la structure change de:
<-- Element Node "some text" <-- TextNode
à quelque chose comme:
<-- Element Node "some text" "more text"
J’ai mis à jour cette réponse, mais il convient également de lire la réponse de Basj à cette question: Remplacez le mot avant le curseur lorsque plusieurs lignes sont disponibles dans contenteditable.
JSFiddle démo ou extrait de code exécutable:
document.getElementById('divTest').onkeyup = function (e) { if (e.keyCode == 32) { getWordPrecedingCaret(this); } }; 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.toSsortingng(); } } 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.toSsortingng().sortingm().split(' '), lastWord = words[words.length - 1]; if (lastWord) { var resultValue = 'some'; // this value is coming from some other function if (resultValue == lastWord) { console.log('do nothing: ' + lastWord); // do nothing } else { console.log('replace word ' + lastWord); /* Find word start and end */ var wordStart = range.endContainer.data.lastIndexOf(lastWord); var wordEnd = wordStart + lastWord.length; console.log("pos: (" + wordStart + ", " + wordEnd + ")"); range.setStart(range.endContainer, wordStart); range.setEnd(range.endContainer, wordEnd); range.deleteContents(); range.insertNode(document.createTextNode(resultValue)); // delete That specific word and replace if with resultValue /* Merge multiple text nodes */ containerEl.normalize(); } return lastWord; } }
Write words here and hit SPACE BAR
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 '' + m + ''; }); }); //html = html.replace(' ', ' ').replace(/\s+/g, ' '); console.log('HTML:', html); console.log('----'); div.html(html); }
Appelez cette fonction sur setinterval
Violon
La solution de Tobías fonctionne bien pour les div. Mais si vous ajoutez plusieurs lignes, cela ne fonctionnera plus.
Voici une solution générale qui fonctionne à la fois pour les div à une ou plusieurs lignes.
- Contenu HTML5Editable avec jQuery
- Comment obtenir le décalage de pixel par rapport à la position actuelle du curseur dans une iframe avec contentEditable
- Insérer du code HTML lorsque le curseur se trouvait dans un contenu modifiable
- contenteditable met le curseur hors de la plage insérée
- Comment puis-je activer “glissable” sur un élément avec contentEditable?
- jQuery: Convertir l’URL du texte en lien en tapant
- Éditeur de texte et position du curseur pouvant être modifiés
- déclencher un événement lorsque contenteditable est modifié
- jquery Définition de la position du curseur dans contenteditable div