在<textarea>
处写一个red
的最佳方法是什么?它会自动为红色这个词I ate tha'red-meat
着色?
即使它没有被空格包围,它也应该着色
因此,例如,它仍然适用于文字reddit
和单词red
。
This是查找包含body {
margin: 0;
}
textarea {
background-color: GhostWhite;
border: 0;
height: 100%;
outline: none;
resize: none;
width: 100%;
}
字词的理想场所。
我有以下代码:
<textarea spellcheck="false"></textarea>
outcum
答案 0 :(得分:1)
所以你可以使用一个contenteditable div,匹配任何前面没有>
的红色,然后将红色替换为:"$1<span class='specialColor'>red</span>‌"
零宽度的非连接字符end用作跨度的分隔符。
document.getElementById('foo').addEventListener('input', function(e) {
var re = /([^\>])red/;
var split = this.innerHTML.replace(re, "$1<span class='specialColor'>red</span>‌");
this.innerHTML = split;
placeCaretAtEnd(this);
})
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
body {
margin: 0;
}
textarea {
background-color: GhostWhite;
border: 0;
height: 100%;
outline: none;
resize: none;
width: 100%;
}
.specialColor {
color:red;
}
<div id="foo" contenteditable spellcheck="false"></div>
声明:
placeCaretAtEnd()方法取自此SO答案:contenteditable, set caret at the end of the text (cross-browser)
答案 1 :(得分:1)
您无法使用textarea
执行此操作,而是使用contenteditable
范围(建议使用span
以避免输入<
时出现问题)并换色通过使用span来子串。
var div = document.getElementById('div');
div.addEventListener('input', function() {
// get the current position
var pos = getCaretCharacterOffsetWithin(this);
// get all word in the content
this.innerHTML = this.innerText.replace(/\w+/g, function(m) {
// create a temporary span element
var temp = document.createElement('span');
// set current word as color
temp.style.color = m;
// check color is valid by rechecking the proeprty
if (temp.style.color) {
// if valid color then replace with temp elements html after setting content
temp.innerHTML = m;
return temp.outerHTML;
}
// else return the word itself
return m;
})
// set caret position
setCaretPosition(this, pos);
})
// following code is copied from following question
// https://stackoverflow.com/questions/26139475/restore-cursor-position-after-changing-contenteditable
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;
}
function setCaretPosition(element, offset) {
var range = document.createRange();
var sel = window.getSelection();
//select appropriate node
var currentNode = null;
var previousNode = null;
for (var i = 0; i < element.childNodes.length; i++) {
//save previous node
previousNode = currentNode;
//get current node
currentNode = element.childNodes[i];
//if we get span or something else then we should get child node
while (currentNode.childNodes.length > 0) {
currentNode = currentNode.childNodes[0];
}
//calc offset in current node
if (previousNode != null) {
offset -= previousNode.length;
}
//check whether current node has enough length
if (offset <= currentNode.length) {
break;
}
}
//move caret to specified offset
if (currentNode != null) {
range.setStart(currentNode, offset);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
&#13;
<span contenteditable="true" id="div">sss</span>
&#13;
注意:对于位置保留代码,请复制自:Restore cursor position after changing contenteditable
更新:如果您只想在任何字词中替换red
,那么您可以这样做:
var div = document.getElementById('div');
div.addEventListener('input', function() {
var pos = getCaretCharacterOffsetWithin(this);
// get all red subtring and wrap it with span
this.innerHTML = this.innerText.replace(/red/g, '<span style="color:red">$&</span>')
setCaretPosition(this, pos);
})
// following code is copied from following question
// https://stackoverflow.com/questions/26139475/restore-cursor-position-after-changing-contenteditable
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;
}
function setCaretPosition(element, offset) {
var range = document.createRange();
var sel = window.getSelection();
//select appropriate node
var currentNode = null;
var previousNode = null;
for (var i = 0; i < element.childNodes.length; i++) {
//save previous node
previousNode = currentNode;
//get current node
currentNode = element.childNodes[i];
//if we get span or something else then we should get child node
while (currentNode.childNodes.length > 0) {
currentNode = currentNode.childNodes[0];
}
//calc offset in current node
if (previousNode != null) {
offset -= previousNode.length;
}
//check whether current node has enough length
if (offset <= currentNode.length) {
break;
}
}
//move caret to specified offset
if (currentNode != null) {
range.setStart(currentNode, offset);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
&#13;
<span contenteditable="true" id="div" style="width:100%;display:block">sss</span>
&#13;
注意:此解决方案存在一些与换行相关的问题,因为内容是HTML并且换行没有任何意义。
答案 2 :(得分:0)
您无法在可编辑输入区域(如input
或textarea
)内的文本中添加部分样式。它被视为单个文本块,只能作为一个整体设置。
但是,可以通过巧妙定位样式化的span
元素来模拟所需的效果。
有一个这样的项目可以随时随地提供文字突出显示。检查出来:Code Mirror Project
我在我的一个个人项目中使用过codemirror。你也应该看看它。 See the editable pane on the left
答案 3 :(得分:0)
我唯一不满意的是它如何处理换行符和标签。 它比仅替换红色更复杂一点,但这样你可以突出显示任何颜色的任何单词,甚至可能在同一元素上混合其中的几个,所以使用的函数是可重用的。
<html>
<head>
<style>
#myTextarea {
border: 1px solid black;
border-radius: 5px;
min-height: 50px;
width: 50%;
}
.hl-red {
color: red;
}
</style>
</head>
<body>
<div id="myTextarea" contenteditable>Test string</div>
<script>
var createHighlighter = function createHighlighter( word ) {
// Let's create a reusable function that can highlight any word.
// You call this function providing the word you want highlighted.
// Then this returns a function that will insert some html spans around each instance of the word.
// You can the call the returned function with any string to get the string saturated with the span tags.
return function highlight( str ) {
// We split on the word we want to highlight, so our array contains all the non-highlighted chunks.
// Since we can call the function multiple times in a row, we will usually want to remove the previous highlights, so we don't double-highlight it.
// This can be easily done with a simple global replace regex.
var chunks;
if (str === '<br>') return '';
else {
chunks = str.replace(/\<span\sclass="hl-red"\>/g, '').replace(/\<\/span\>/g, '').split(word);
// Then we add the non-highlighted text + the <span> + the highlighted word.
return chunks.reduce(function( html, chunk, index ) {
html += chunk;
// Add the highlighted word, except for the last chunk, since that's just the end of the string.
if ((index + 1) !== chunks.length) html += '<span class="hl-red">' + word + '</span>';
return html;
}, '');
}
};
};
var wordToHighlight = 'red';
var highlightRed = createHighlighter( wordToHighlight );
var highlightArea = function highlightArea( event ) {
event.target.innerHTML = highlightRed( event.target.innerHTML );
};
document.querySelector('#myTextarea').addEventListener('keyup', highlightArea);
</script>
</body>
</html>