2016-11-22 22 views
6

mam ten contentedittable divjak zdobyć pozycję daszka o contenteditable div, który zawiera obrazy

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

Oto opis obrazu na wyjściu kodu enter image description here

więc chcę dostać karetkę pozycja div i pozwala założyć, że kursor znajduje się za ostatnim znakiem. A to jest mój kod do uzyskania pozycji daszka

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

Ale problemem jest to, że zwraca 6 zamiast 14. Pozycja opiekuna powraca do 0 po obrazie. Czy istnieje sposób, w jaki mogę uzyskać pozycję opiekuna, aby w tym przypadku być 14.

EDIT

Chcę również wstawić jakiś element, zaczynając od położenia karetki. tak to jest moja funkcja to zrobić

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); 
} 

Odpowiedz

6

Zobacz Tim Down's odpowiedź na Get a range's start and end offset's relative to its parent container.

spróbować użyć funkcji musi uzyskać indeks zaznaczenia z elementów zagnieżdżonych takiego:

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>

napisałem własną funkcję, w oparciu o Tim Downa, który działa jak ty chcieć tego. Zmieniłem treeWalker w celu filtrowania NodeFilter.ELEMENT_NODE utworzonych z NodeFilter.SHOW_TEXT, a teraz również elementy <img/> są przetwarzane wewnątrz naszej pętli. Zaczynam od przechowywania range.startOffset, a następnie powracam do wszystkich węzłów drzewa wyboru. Jeśli znajdzie węzeł img, doda tylko 1 do pozycji; jeśli bieżący element węzła jest inny niż nasz range.startContainer, wówczas dodaje on długość tego węzła. Pozycja jest zmieniana przez inną zmienną lastNodeLength, która jest dodawana do charCount w każdej pętli. Na koniec dodaje to, co pozostało w lastNodeLength do charCount, gdy istnieje pętla i mamy poprawne końcowe położenie karetki, w tym elementy obrazu.

końcowy kod roboczych(zwraca 14 na końcu, dokładnie tak jak powinien i chcesz)

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

Twój kod jest fajne, ale trzeba wykryć wszystkie html zawartość elementu div nie zawiera tekstu, ponieważ będę wstawiał niektóre znaki do elementu div w pozycji daszka. Spójrz na moje pytanie edytuj. –

+0

@doggiebrezy Sprawiłem, że działa tak, jak chcesz. Zobacz moją zaktualizowaną odpowiedź. Przetestowałem go w najnowszych przeglądarkach Chrome i Firefox. To nie działa na IE. –

+0

dziękuję za edycję, ale pomóżcie mi z ostatnią rzeczą. Teraz chcę wstawić jakiś tekst lub obraz w pozycji opiekuńczej, a więc podzielę div.html, ale problem polega na tym, że zakładając, że pozycja karetki to 11, wstawiony tekst nie liczy tego obrazu jako jednego, ale całego img.html tam błędnie umieszczając punkt, w którym ma być wstawiony, proszę pomóż mi zliczyć ile stringów w div.html w tym element img –

Powiązane problemy