我有一个div,在我的学校项目网站上被用作用户友好的文本编辑器。但是,如果我选择编辑器中的所有文本并尝试用<code> tags </code>
包围它,我无法将光标从中取出,它会不断将我键入的任何内容添加到同一标签中,这<code>
.
一段时间后,我放弃了它,但后来我找到了这个答案,并试图修改那里提到的 jsfiddle,希望让它工作。但是没有运气。
如果我,比方说,选择任何行中的最后一个单词并用<code>
标签包围它,我能够将光标从没有包围文本的地方移出,但最后没有明文可以跳转到,所以光标卡在<code>
如何确保光标不会卡在添加的标签中?也许有一种将光标移出的方法?
js小提琴
function surroundSelection() {
var code = document.createElement("code");
code.style.fontStyle = "italic";
code.style.color = "#333";
code.style.background = "#ddd";
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0).cloneRange();
range.surroundContents(code);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
div, input {
padding:10px;
}
div {border:1px solid;}
<input type="button" onclick="surroundSelection()" value="Surround">
<div contenteditable="true">One two three four</div>
这里有一个有点古怪的解决方法。不再使用环绕声,而是将内容复制到新节点中。然后我们在末尾添加一个空格。现在可以在代码块之后单击,即使选择了所有文本也是如此。
编辑:添加了sel.collapseToEnd();根据评论(谢谢)。它通过将用户直接置于正常的键入上下文中来改善体验。但是,空间仍然是必需的,没有它就无法工作。
编辑:现在为开始和结束添加空间。
编辑:删除垫片以发送到服务器。
function surroundSelection() {
let code = document.createElement("code");
code.style.fontStyle = "italic";
code.style.color = "#333";
code.style.background = "#ddd";
const newSpan = () => {
let span = document.createElement('span');
span.classList.add('codespacer');
span.innerHTML = ' ';
return span;
}
if (window.getSelection) {
let sel = window.getSelection();
if (sel.rangeCount) {
let range = sel.getRangeAt(0).cloneRange();
code.innerHTML = range.toString();
range.deleteContents();
range.insertNode(newSpan());
range.insertNode(code);
range.insertNode(newSpan());
sel.removeAllRanges();
sel.addRange(range);
sel.collapseToEnd();
}
}
}
function getContentForSave() {
let codeSection = document.querySelector('#codeSection');
// Copy into a temporary element (otherwise the text will change in the UI)
let tempSection = document.createElement('div');
tempSection.innerHTML = codeSection.innerHTML;
console.log(`Before: ${tempSection.innerHTML}`);
// Remove all codespacers
let spacers = tempSection.querySelectorAll('.codespacer');
for(let space of spacers) {
tempSection.removeChild(space);
}
console.log(`After: ${tempSection.innerHTML}`);
return tempSection.innerHTML;
}
div,
input {
padding: 10px;
}
div {
border: 1px solid;
}
<input type="button" onclick="surroundSelection()" value="Surround">
<div contenteditable="true" id="codeSection">One two three four</div>
<input type="button" onclick="getContentForSave();" value="Test For Save">
我认为您可以克服它的一种方法是在代码后面textNode
附加一个空白区域,然后将光标移动到其位置。这样用户就可以立即继续写入普通文本。
以下是细分:
- 创建一个包含带有
document.createTextNode('u00A0')
的空格字符的文本节点。请注意,文字' '
在我的浏览器(Chrome 70)上不起作用。 - 将新的空文本节点添加到
div
中。 - 使用
range.setEnd()
将新的空文本节点添加到当前range
,以便我们可以使用selection.collapseToEnd()
方法将光标移动到最后。
全部(小提琴)
+ function addPad() {
+ var $input = document.querySelector('div');
+ var pad = document.createTextNode('u00A0');
+ $input.appendChild(pad);
+ return pad;
+ }
function surroundSelection() {
var sel = window.getSelection();
if (!sel || !sel.rangeCount) return;
var code = document.createElement("code");
var range = sel.getRangeAt(0).cloneRange();
range.surroundContents(code);
sel.removeAllRanges();
sel.addRange(range);
+ // create empty node + add it to div
+ var padNode = addPad();
+ // update the current range to include the empty node.
+ // since we only add 1 space, the `offset` is set to 1.
+ range.setEnd(padNode, 1);
+ // move the cursor to very end of range
+ sel.collapseToEnd();
}