모든 Rangy Q &을 조사했지만이 경우에는 아무런 변화가 없습니다.Rangy는 contenteditable div의 백 스페이스에서 캐럿 위치를 잃습니다.
나는 때마다 사용자 유형 뭔가, 그것은 내용과 형식 특정 토큰을 구문 분석 호출의 contentEditable
<div id="area" style="width:100%;height:2em;"
contentEditable="true";
onkeyup="formatText();"
></div>
다음과 같은 기능을 가지고있다.
function formatText() {
var el = document.getElementById('area');
var savedSel = saveSelection(el); // calls Rangy function
var tokenColor;
// removes html tags before passing the expression to the parser
var userInput = document.getElementById('area').innerHTML.replace(/(<([^>]+)>)/g,"").replace(/&/g, "").replace(/>/g, ">").replace(/</g, "<").replace(/<span[^>]*>+<\/span>/, "");
var i, newHTML=[];
tokenType=[]; // [NUMBER,+,(,NUMBER,..]
tokenArray=[]; // [3,+,(5,...]
var resultOutput = parse(userInput); // parser also fills tokenType and tokenArray
for (i=0; i<tokenArray.length-1; i++){
newHTML += "<span style='color: " + tokenColor + " '>" + tokenArray[i] + "</span>";
} // newHTML looks like <span style='color: red'>3</span><span style='color: black'>+</span> etc.
el.innerHTML = newHTML; // replaces content of <div> with formatted text
restoreSelection(el, savedSel); // calls Rangy function to restore cursor position
}
나는이 포럼에 다른 글에서 저자가 제시 한 다음 돌아 다니기에 알맞은 기반 기능을 사용 : 내가 문자를 삭제하려고 할 때까지
function saveSelection(containerEl) {
var charIndex = 0, start = 0, end = 0, foundStart = false, stop = {};
var sel = rangy.getSelection(), range;
function traverseTextNodes(node, range) {
if (node.nodeType == 3) {
if (!foundStart && node == range.startContainer) {
start = charIndex + range.startOffset;
foundStart = true;
}
if (foundStart && node == range.endContainer) {
end = charIndex + range.endOffset;
throw stop;
}
charIndex += node.length;
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
traverseTextNodes(node.childNodes[i], range);
}
}
}
if (sel.rangeCount) {
try {
traverseTextNodes(containerEl, sel.getRangeAt(0));
} catch (ex) {
if (ex != stop) {
throw ex;
}
}
}
return {
start: start,
end: end
};
}
function restoreSelection(containerEl, savedSel) {
var charIndex = 0, range = rangy.createRange(), foundStart = false, stop = {};
range.collapseToPoint(containerEl, 0);
function traverseTextNodes(node) {
if (node.nodeType == 3) {
var nextCharIndex = charIndex + node.length;
if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
range.setStart(node, savedSel.start - charIndex);
foundStart = true;
}
if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
range.setEnd(node, savedSel.end - charIndex);
throw stop;
}
charIndex = nextCharIndex;
}
else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
traverseTextNodes(node.childNodes[i]);
}
}
}
try {
traverseTextNodes(containerEl);
} catch (ex) {
if (ex == stop) {
rangy.getSelection().setSingleRange(range);
} else {
throw ex;
}
}
}
모든 것이 완벽하게 작동합니다. 이 시점에서 커서는 div 시작 부분에서 점프합니다.
이것이 일어날 수있는 이유는 무엇입니까?
감사합니다.
div의 전체 내용을 파괴하고 innerHTML로 바꾸므로 선택한 노드가 더 이상 존재하지 않습니다. innerHTML을 사용하는 대신, 원하지 않는 노드를 수동으로 제거해야합니다. –
@GGG : 두 번째 코드 블록은 문자 인덱스 기반 저장 및 선택 복원을 수행하므로 'innerHTML'교체 후 보이는 텍스트가 변경되지 않는 한 작동해야합니다. –
@TimDown 지금 무슨 뜻인지 알기 전에 그 부분을 방금 건너 뛴 것입니다. 나는 아직도이 일에 대한 나의 의구심을 가지고있다. 정규식 중 일부는 깨진 마크 업을 만드는 것처럼 보입니다. "".replace (/ (<([^>) +)>) /, '') // "" –