2013-05-24 11 views
7

Ich habe eine contenteditable div in denen ich mehrere Tags (br, b, u, ich) und Text und ich muss die Caret-Position relativ zum div, einschließlich aller Tags zu bekommen .Holen Sie sich Caret-Position in contenteditable div einschließlich Tags

Zum Beispiel:

<div id="h" contenteditable="true">abc<b>def<br>ghi</b>jkl</div> 

Wenn sich der Cursor zwischen g und h ist, muss ich die Position der Einfügemarke 14. Das Problem ist, dass die gefundenen Methoden, die einen TreeWalker verwenden, funktionieren nicht in diesem Fall . Das Fett-Tag wurde nicht gefunden ... wahrscheinlich, weil es nicht geschlossen ist. Auch ich habe mehrere Methoden ausprobiert aber immer noch kein Glück.

Ich brauche es in Firefox zu arbeiten. Danke.

+0

Warum brauchen Sie diese Nummer? Es ist im Wesentlichen bedeutungslos, da es viele Möglichkeiten gibt, dasselbe DOM mit unterschiedlichem HTML zu repräsentieren, was sich auf die Zahl auswirkt (z. B. durch Verwenden von "
" anstelle von "
"). Ich gehe davon aus, dass Sie dies möchten, damit Sie einen Offset relativ zu der HTML-Zeichenfolge erhalten können, die Sie vom Server an den Browser senden. –

+0

ja ... genau deshalb brauche ich die nummer. Ich habe mehrere Mittel versucht, aber immer noch keinen Erfolg. – helldrain

+1

Es gibt keine Möglichkeit, die ursprüngliche HTML-Zeichenfolge über das DOM zurückzuerhalten. Daher müssen Sie die Seite erneut über Ajax anfordern, den HTML-Code analysieren und ihn dem aktuellen DOM zuordnen. Es wird ziemlich schwierig werden. –

Antwort

20

Haben Sie das versucht? Get a range's start and end offset's relative to its parent container

Direkter Link auf die jsfiddle: https://jsfiddle.net/TjXEG/1/

Funktionscode:

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

function showCaretPos() { 
    var el = document.getElementById("test"); 
    var caretPosEl = document.getElementById("caretPos"); 
    caretPosEl.innerHTML = "Caret position: " + getCaretCharacterOffsetWithin(el); 
} 

document.body.onkeyup = showCaretPos; 
document.body.onmouseup = showCaretPos; 
+7

Vielen Dank für Ihre Antwort. Das Problem ist, dass die
bei der Bestimmung der Caret-Position nicht berücksichtigt wird. – helldrain

+1

@helldrain Ich frage mich, ob Sie es geschafft haben, eine Lösung zu finden, die die Tags enthält. –

+0

gibt es eine Funktion, die auch die Länge der Tags enthält. ? –

3

gerade dies so zu tun hatte, dass eine Arbeitslösung (einige Tests erforderlich sein kann)

Grundidee ist zu:

  1. textcontent Position mit dieser Methode erhalten: Get caret (cursor) position in contentEditable area containing HTML content

  2. iterieren innerHTML- eines Elements der textcontent Position

  3. wenn HTML-Tag oder Einheit angetroffen wird, durchlaufen, bis normale char, dann weiter

Beispielcode hier:

function getHTMLCaretPosition(element) { 
var textPosition = getCaretPosition(element), 
    htmlContent = element.innerHTML, 
    textIndex = 0, 
    htmlIndex = 0, 
    insideHtml = false, 
    htmlBeginChars = ['&', '<'], 
    htmlEndChars = [';', '>']; 


if (textPosition == 0) { 
    return 0; 
} 

while(textIndex < textPosition) { 

    htmlIndex++; 

    // check if next character is html and if it is, iterate with htmlIndex to the next non-html character 
    while(htmlBeginChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) { 
    // console.log('encountered HTML'); 
    // now iterate to the ending char 
    insideHtml = true; 

    while(insideHtml) { 
     if (htmlEndChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) { 
     if (htmlContent.charAt(htmlIndex) == ';') { 
      htmlIndex--; // entity is char itself 
     } 
     // console.log('encountered end of HTML'); 
     insideHtml = false; 
     } 
     htmlIndex++; 
    } 
    } 
    textIndex++; 
} 

//console.log(htmlIndex); 
//console.log(textPosition); 
// in htmlIndex is caret position inside html 
return htmlIndex; 
} 
+3

Du bist mein Held. Das hat wunderbar funktioniert und mir Stunden der Tränen erspart. –

Verwandte Themen