我有一个自定义textarea.在这个例子中,它随机地使字母变为红色或绿色.
var mydiv = document.getElementById('mydiv'),myta = document.getElementById('myta'); function updateDiv() { var fc; while (fc = mydiv.firstChild) mydiv.removeChild(fc); for (var i = 0; i < myta.value.length; i++) { var span = document.createElement('span'); span.className = Math.random() < 0.5 ? 'green' : 'red'; span.appendChild(document.createTextNode(myta.value[i])); mydiv.appendChild(span); } }; myta.addEventListener('input',updateDiv);
body { position: relative } div,textarea { -webkit-text-size-adjust: none; width: 100%; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; font: 1rem sans-serif; padding: 2px; margin: 0; border-radius: 0; border: 1px solid #000; resize: none; } textarea { position: absolute; top: 0; color: transparent; background: transparent; } .red { color: #f00 } .green { color: #0f0 }
<div id="mydiv"></div> <textarea id="myta" autofocus=""></textarea>
有一个带有textarea的输出div.因此textarea不会掩盖其下面的任何彩色物品,它的颜色和背景都设置为透明.除了插入符(用户代理提供的闪烁光标)是透明的以外,一切都在这里工作.
如果我将div设置在textarea之上并给它指针-event:none,则textarea仍然可以在下面看到.这种安排也使得平滑滚动变得困难,因此它对我不起作用.
解决方法
只需插入自己的插入符号!
function blink() { document.getElementById('caret').hidden ^= 1; blinkTimeout = setTimeout(blink,500); } var mydiv = document.getElementById('mydiv'),myta = document.getElementById('myta'),blinkTimeout = setTimeout(blink,500),lastSelectionStart = 0,lastSelectionEnd = 0,whichSelection = true; function updateDiv() { var fc; while (fc = mydiv.firstChild) mydiv.removeChild(fc); if (myta.selectionStart != lastSelectionStart) { lastSelectionStart = myta.selectionStart; whichSelection = false; } if (myta.selectionEnd != lastSelectionEnd) { lastSelectionEnd = myta.selectionEnd; whichSelection = true; } var cursorPos = whichSelection ? myta.selectionEnd : myta.selectionStart; for (var i = 0; i < myta.value.length; i++) { if (i == cursorPos) { var caret = document.createElement('span'); caret.id = 'caret'; caret.appendChild(document.createTextNode('\xA0')); mydiv.appendChild(caret); clearTimeout(blinkTimeout); blinkTimeout = setTimeout(blink,500); } var span = document.createElement('span'); span.className = Math.random() < 0.5 ? 'green' : 'red'; span.appendChild(document.createTextNode(myta.value[i])); mydiv.appendChild(span); } if (myta.value.length == cursorPos) { var caret = document.createElement('span'); caret.id = 'caret'; caret.appendChild(document.createTextNode('\xA0')); mydiv.appendChild(caret); clearTimeout(blinkTimeout); blinkTimeout = setTimeout(blink,500); } }; myta.addEventListener('input',updateDiv); myta.addEventListener('focus',updateDiv); myta.addEventListener('mousedown',function() { setTimeout(updateDiv,0); }); myta.addEventListener('keydown',0); }); myta.addEventListener('blur',function() { document.getElementById('caret').hidden = true; clearTimeout(blinkTimeout); });
body { position: relative } div,textarea { -webkit-text-size-adjust: none; width: 100%; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; font: 1rem sans-serif; padding: 2px; margin: 0; border-radius: 0; border: 1px solid #000; resize: none; } textarea { position: absolute; top: 0; color: transparent; background: transparent; } .red { color: #f00 } .green { color: #0f0 } #caret { display: inline-block; position: absolute; width: 1px; background: #000; } #caret[hidden] { display: none }
<div id="mydiv"><span id="caret"> </span></div> <textarea id="myta" autofocus=""></textarea>
我这里有一个< span> #caret插入到div中,通过使用JS切换其隐藏属性,每隔500ms闪烁一次.为了复制浏览器行为,我必须检测它是selectStart还是者插入符实际所在的selectionEnd,并使其在输入文本时保持稳定.
当跨度不是固定长度或嵌套时,这有点难以实现,但它比使用更复杂的荧光笔的contentEditable更容易.此功能会将插入符号插入正确的位置:
function insertNodeAtPosition(node,refNode,pos) { if (typeof(refNode.nodeValue) == 'string') refNode.parentNode.insertBefore(node,refNode.splitText(pos)); else { for (var i = 0; i < refNode.childNodes.length; i++) { var chNode = refNode.childNodes[i]; if (chNode.textContent.length <= pos && i != refNode.childNodes.length - 1) pos -= chNode.textContent.length; else return insertNodeAtPosition(node,chNode,pos); } } }
用法(我是插入它的位置):
var caret = document.createElement('span'); caret.id = 'caret'; caret.appendChild(document.createTextNode('\xA0')); insertNodeAtPosition(caret,mydiv,i); clearTimeout(blinkTimeout); blinkTimeout = setTimeout(blink,500);