2016-11-22 2 views
6

Je possède ce contentedittable divcomment obtenir la position de caret d'un contenteditable div qui contient des images

<div contenteditable="true" id="text">minubyv<img src="images/smiley/Emoji Smiley-01.png" class="emojiText" />iubyvt</div> 

Voici une description de l'image de la sortie de code enter image description here

donc je veux obtenir le caret position de la div et laisse supposer que le curseur est après le dernier caractère. Et voici mon code pour obtenir la position de caret

function getCaretPosition(editableDiv) { 
    var caretPos = 0, 
    sel, range; 
    if (window.getSelection) { 
    sel = window.getSelection(); 
    if (sel.rangeCount) { 
     range = sel.getRangeAt(0); 
     if (range.commonAncestorContainer.parentNode == editableDiv) { 
     caretPos = range.endOffset; 
     } 
    } 
    } else if (document.selection && document.selection.createRange) { 
    range = document.selection.createRange(); 
    if (range.parentElement() == editableDiv) { 
     var tempEl = document.createElement("span"); 
     editableDiv.insertBefore(tempEl, editableDiv.firstChild); 
     var tempRange = range.duplicate(); 
     tempRange.moveToElementText(tempEl); 
     tempRange.setEndPoint("EndToEnd", range); 
     caretPos = tempRange.text.length; 
    } 
    } 
    return caretPos; 
} 

var update = function() { 
    console.log(getCaretPosition(this)); 
}; 
$('#text').on("mousedown mouseup keydown keyup", update); 

Mais le problème est qu'il retourne 6 au lieu de 14. La position du curseur revient à 0 après l'image. S'il vous plaît, est-ce que je peux obtenir la position du curseur 14 dans ce cas.

EDIT

Je veux aussi insérer un élément à partir de la position de caret. c'est donc ma fonction de le faire

selectStart = 0; 
var update = function() { 
    selectStart = getCaretPosition(this); 
}; 
function insertEmoji(svg){ 
    input = $('div#text').html(); 
    beforeCursor = input.substring(0, selectStart); 
    afterCursor = input.substring(selectStart, input.length); 
    emoji = '<img src="images/smiley/'+svg+'.png" class="emojiText" />'; 
    $('div#text').html(beforeCursor+emoji+afterCursor); 
} 

Répondre

6

Voir Tim Down's réponse sur Get a range's start and end offset's relative to its parent container.

Essayez d'utiliser la fonction qu'il doit obtenir l'index de sélection avec des éléments imbriqués comme ceci:

function getCaretCharacterOffsetWithin(element) { 
 
    var caretOffset = 0; 
 
    var doc = element.ownerDocument || element.document; 
 
    var win = doc.defaultView || doc.parentWindow; 
 
    var sel; 
 
    if (typeof win.getSelection != "undefined") { 
 
     sel = win.getSelection(); 
 
     if (sel.rangeCount > 0) { 
 
      var range = win.getSelection().getRangeAt(0); 
 
      var preCaretRange = range.cloneRange(); 
 
      preCaretRange.selectNodeContents(element); 
 
      preCaretRange.setEnd(range.endContainer, range.endOffset); 
 
      caretOffset = preCaretRange.toString().length; 
 
     } 
 
    } else if ((sel = doc.selection) && sel.type != "Control") { 
 
     var textRange = sel.createRange(); 
 
     var preCaretTextRange = doc.body.createTextRange(); 
 
     preCaretTextRange.moveToElementText(element); 
 
     preCaretTextRange.setEndPoint("EndToEnd", textRange); 
 
     caretOffset = preCaretTextRange.text.length; 
 
    } 
 
    return caretOffset; 
 
} 
 

 
var update = function() { 
 
    console.log(getCaretCharacterOffsetWithin(this)); 
 
}; 
 
$('#text').on("mousedown mouseup keydown keyup", update);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div contenteditable="true" id="text">minubyv<img src="https://themeforest.net/images/smileys/happy.png" class="emojiText" />iubyvt</div>

j'ai écrit ma propre fonction, basée sur Tim de Down, qui fonctionne comme vous le veux. J'ai changé le treeWalker pour filtrer NodeFilter.ELEMENT_NODE insted de NodeFilter.SHOW_TEXT, et maintenant <img/> les éléments sont également traités dans notre boucle. Je commence par stocker le range.startOffset et ensuite recurse à travers tous les noeuds de l'arbre de sélection. S'il trouve un nœud img, il ajoute seulement 1 à la position; Si l'élément de nœud actuel est différent de notre range.startContainer, il ajoute la longueur de ce nœud. La position est modifiée par une variable différente lastNodeLength qui s'ajoute à la charCount à chaque boucle. Enfin, il ajoute ce qui reste dans le lastNodeLength au charCount lorsqu'il existe la boucle et que nous avons la position finale correcte du curseur, y compris les éléments de l'image.

Code de travail final(il retourne 14 à la fin, exactement comme il se doit et que vous voulez)

function getCharacterOffsetWithin_final(range, node) { 
 
    var treeWalker = document.createTreeWalker(
 
     node, 
 
     NodeFilter.ELEMENT_NODE, 
 
     function(node) { 
 
      var nodeRange = document.createRange(); 
 
      nodeRange.selectNodeContents(node); 
 
      return nodeRange.compareBoundaryPoints(Range.END_TO_END, range) < 1 ? 
 
       NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; 
 
     }, 
 
     false 
 
    ); 
 

 
    var charCount = 0, lastNodeLength = 0; 
 

 
    if (range.startContainer.nodeType == 3) { 
 
     charCount += range.startOffset; 
 
    } 
 

 
    while (treeWalker.nextNode()) { 
 
     charCount += lastNodeLength; 
 
     lastNodeLength = 0; 
 
     
 
     if(range.startContainer != treeWalker.currentNode) { 
 
      if(treeWalker.currentNode instanceof Text) { 
 
       lastNodeLength += treeWalker.currentNode.length; 
 
      } else if(treeWalker.currentNode instanceof HTMLBRElement || 
 
         treeWalker.currentNode instanceof HTMLImageElement /* || 
 
         treeWalker.currentNode instanceof HTMLDivElement*/) 
 
      { 
 
       lastNodeLength++; 
 
      } 
 
     } 
 
    } 
 
    
 
    return charCount + lastNodeLength; 
 
} 
 

 
var update = function() { 
 
    var el = document.getElementById("text"); 
 
    var range = window.getSelection().getRangeAt(0); 
 
    console.log("Caret pos: " + getCharacterOffsetWithin_final(range, el)) 
 
}; 
 
$('#text').on("mouseup keyup", update);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div contenteditable="true" id="text">minubyv<img contenteditable="true" src="https://themeforest.net/images/smileys/happy.png" class="emojiText" />iubyvt</div>

+0

Votre code est cool, mais j'ai besoin de détecter tous les fichiers html Le contenu de la div ne contient pas le texte, car je vais insérer quelques caractères dans la div à la position du curseur. Regardez ma question éditer. –

+0

@doggiebrezy Je l'ai fait fonctionner comme vous le voulez. Voir ma réponse mise à jour. Je l'ai testé sur Chrome et Firefox. Cela ne fonctionne pas sur IE cependant. –

+0

merci pour votre modification, mais s'il vous plaît aidez-moi avec une dernière chose. Maintenant, je veux insérer du texte ou une image à la position du curseur et ainsi je diviser le div.html mais le problème est que supposant que la position du curseur est 11, le texte inséré ne compte pas cette image en tant qu'un img entier.html là en déplaçant le point où il est censé être inséré, s'il vous plaît pouvez-vous m'aider à compter combien de chaîne dans le div.html y compris l'élément img –