2016-11-22 5 views
6

이미지가 포함 된의 contentEditable 사업부의 캐럿 위치를 가져 오는 방법을 enter image description here나는이 contentedittable DIV 여기</p> <pre><code><div contenteditable="true" id="text">minubyv<img src="images/smiley/Emoji Smiley-01.png" class="emojiText" />iubyvt</div> </code></pre> <p>이

그래서 난 캐럿을 얻기 위해 원하는 코드 출력의 이미지에 대한 설명입니다 div의 위치이며 커서가 마지막 문자 뒤에 있다고 가정합니다. 그리고 이것은 캐럿 위치

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

를 받고 내 코드입니다 그러나 문제는 6 대신 14 반환합니다. 캐럿 위치는 이미지 다음에 0으로 되돌아갑니다. 이 경우에는 캐럿 위치를 14으로 가져올 수있는 방법이 있습니까?

편집 나는 또한 caret 위치에서 시작하여 몇 가지 요소를 삽입 할

. 그래서 이것은

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

답변

6

Get a range's start and end offset's relative to its parent containerTim Down's 답변을 참조하십시오 그렇게 내 기능입니다. 난 내 자신의 기능을 썼다

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>

, 팀 다운을 기반으로, 당신처럼 작동 : 함수를 사용하는

봅니다 그는이 같은 중첩 된 요소로 선택 인덱스를 얻을 수있다 원하는. treeWalkerNodeFilter.ELEMENT_NODE insted가 NodeFilter.SHOW_TEXT 인 필터로 변경했으며 현재 <img/> 요소도 루프 내부에서 처리됩니다. 먼저 range.startOffset을 저장 한 다음 모든 선택 트리 노드를 반복합니다. img 노드를 찾으면 위치에 1을 더합니다. 현재 노드 요소가 range.startContainer과 다른 경우 노드의 길이를 추가합니다. 위치는 다른 루프 lastNodeLength에 의해 변경되며 각 루프마다 charCount에 추가됩니다. 마지막으로, 루프에 존재하는 lastNodeLength에 남아있는 것이 무엇이든 에 추가하고 이미지 요소를 포함하여 올바른 최종 캐럿 위치를 갖습니다.

최종 작업 코드(정확히 예상대로, 마지막에 14을 반환하고 당신이 원하는)

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

귀하의 코드는 시원하지만 난 모든 것을 감지 할 필요가 HTML div의 내용이 텍스트를 제공하지 않습니다. 왜냐하면 내가 caret 위치의 div에 일부 문자를 삽입하기 때문입니다. 내 질문을 봐 편집하십시오. –

+0

@doggiebrezy 당신이 원하는대로 작동 시켰습니다. 내 업데이트 답변을 참조하십시오. 최신 Chrome 및 Firefox에서 테스트했습니다. 그것은 비록 IE에서 작동하지 않습니다. –

+0

편집 해 주셔서 감사합니다.하지만 마지막으로 한 가지만 도와주세요. 이제 저는 캐럿 위치에 텍스트 나 이미지를 삽입하려고합니다. 따라서 div.html을 분할했는데 문제는 캐럿 위치가 11이라고 가정하면 삽입 된 텍스트가 그 이미지를 하나의 전체 이미지로 계산하지 않습니다.html 거기에 삽입 할 수있는 지점을 잘못 배치하여, 제발 내가 얼마나 많은 문자열을 div.html img 요소를 포함하여 계산할 수 있습니다 –