所以我想用javascript制作一个所见即所得的编辑器.我正在尝试做的是:当我没有做出选择并且只将插入符号放在一个单词上时,我想选择该单词,对其执行命令,然后将插入符号移回其位置.
例:
在执行代码之前(插入符号应位于函数之后):
使这个词变老
后:
使这个词加粗|
jsFiddle示例:jsFiddle
到目前为止,我的代码:
if (window.getSelection && (sel = window.getSelection()).modify) {
doc.focus(); // the editor
var range = sel.getRangeAt(0);
var oldRange = document.createRange();
oldRange.setStart(range.startContainer, range.startOffset);
oldRange.setEnd(range.endContainer, range.endOffset);
sel.collapseToStart();
sel.modify("move", "forward", "character");
sel.modify("move", "backward", "word");
sel.modify("extend", "forward", "word");
document.execCommand(command, false, value);
// Restore selection, Dosen't work as I expected
sel.removeAllRanges();
sel.addRange(oldRange);
}
解决方法:
问题是,在运行document.execCommand之后,它会立即重置范围,您可以在oldRange上执行console.log并注释掉document.execCommand行以进行确认.保存旧范围的唯一方法是序列化它,就像我在下面的示例中所做的那样.看一看
解
changeStyle = function(command) {
var sel;
var doc = document.getElementById('editor');
if (window.getSelection && (sel = window.getSelection()).modify) {
doc.focus();
var range = sel.getRangeAt(0);
var oldRange = saveCaret(doc);
sel.collapseToStart();
sel.modify("move", "forward", "character");
sel.modify("move", "backward", "word");
sel.modify("extend", "forward", "word");
document.execCommand(command, false, null);
// Restore selection, well, it isn't restoring it
restoreCaret(doc, oldRange)
}
}
saveCaret = function(container) {
var range = window.getSelection().getRangeAt(0);
var preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(container);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
var start = preSelectionRange.toString().length;
return {
start: start,
end: start + range.toString().length
};
};
restoreCaret = function(container, position) {
var charIndex = 0, range = document.createRange();
range.setStart(container, 0);
range.collapse(true);
var nodeStack = [container], node, foundStart = false, stop = false;
while (!stop && (node = nodeStack.pop())) {
if (node.nodeType == 3) {
var nextCharIndex = charIndex + node.length;
if (!foundStart && position.start >= charIndex && position.start <= nextCharIndex) {
range.setStart(node, position.start - charIndex);
foundStart = true;
}
if (foundStart && position.end >= charIndex && position.end <= nextCharIndex) {
range.setEnd(node, position.end - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
var i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
<button onclick="changeStyle('bold')">
Bold
</button>
<div contentEditable=true id="editor">
Try make a word bold without make a selection, the caret will either jump to the start of the word or the end.
It should stay on its position.
</div>