2013-05-24 18 views
7

Mam contenteditable div, w którym mam wiele znaczników (br, b, u, i) i tekst i potrzebuję uzyskać pozycję caret względem div, w tym wszystkie znaczniki .Uzyskać pozycję caret w contenteditable div, w tym znaczniki

Na przykład:

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

Gdy kursor jest od g do h, muszę być pozycji daszka 14. Problemem jest to, że nie znaleziono metody, które wykorzystują treeWalker nie działają w tym przypadku . Pogrubiona etykieta nie została znaleziona ... prawdopodobnie dlatego, że nie jest zamknięta. Również próbowałem kilku metod, ale wciąż nie ma szczęścia.

Potrzebuję go do pracy w Firefoksie. Dziękuję.

+0

Dlaczego trzeba ten numer? Zasadniczo jest to bezsensowne, ponieważ istnieje wiele sposobów reprezentowania tego samego DOM z innym kodem HTML, który wpłynie na liczbę (np. Poprzez użycie '
' zamiast "
"). Zakładam, że chcesz tego, aby uzyskać przesunięcie względem ciągu HTML wysyłanego z serwera do przeglądarki. –

+0

tak ... właśnie dlatego potrzebuję tego numeru. Próbowałem kilka sposobów, ale nadal nie ma sukcesu. – helldrain

+1

Nie ma sposobu na odzyskanie oryginalnego ciągu HTML za pośrednictwem DOM, więc musisz ponownie poprosić o stronę za pośrednictwem Ajax, przeanalizować kod HTML i dopasować go do bieżącego DOM. To będzie dość trudne. –

Odpowiedz

20

Czy próbowałeś tego? Get a range's start and end offset's relative to its parent container

Bezpośredni link do jsfiddle: Kod https://jsfiddle.net/TjXEG/1/

Funkcja:

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

Dziękuję za odpowiedź. Problem polega na tym, że
nie jest brany pod uwagę przy ustalaniu położenia karetki. – helldrain

+1

@helldrain Zastanawiam się, czy udało Ci się znaleźć rozwiązanie zawierające tagi. –

+0

Czy istnieje funkcja, która obejmuje również długość znaczników. ? –

3

prostu musiałem to zrobić, więc nie jest jakiś roztwór roboczy (mogą być wymagane niektóre badania)

podstawowym pomysłem jest:

  1. uzyskać pozycję textContent użyciu tej metody: Get caret (cursor) position in contentEditable area containing HTML content

  2. iterację innerHTML elementu do pozycji textContent

  3. razie napotkania znacznika html lub podmiot, iterację nim aż normalnego char, a następnie kontynuować

przykładowy kod tutaj:

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

Jesteś moim bohaterem. To działało pięknie i oszczędzało mi godzin łez. –