制作像div
这样的Twitter推文框contenteditable
是我的任务。
我想将60个字符后的div文本颜色更改为红色。类似于Twitter在120个字符后所做的事情。
到目前为止,我已经能够弄清楚如何更改额外文本的颜色,但我对光标位置的问题感到困惑。
以下是我尝试过的代码的小提琴:https://jsfiddle.net/Bharadwajdaya/36sn0dqn/1/
下面的代码段:
var red_string;
$('#div_editable').on("keyup", function(e) {
//console.log
var content = this.innerText;
var siz = this.innerText.length;
if (siz > 60) {
var contentEditableElement = document.getElementById("div_editable");
var con = this.innerText.substring(0, 60);
red_string = this.innerText.substring(60, siz);
var newString = "<span class='highlight'>" + red_string + "</span>";
console.log(newString + con);
$("#div_editable").html(con + newString);
document.getElementById("div_editable").focus();
setSelectionRange(document.getElementById("div_editable"), siz, siz);
setCaretToPos(siz - 61)
}
});
function setCaretToPos(siz) {
console.log(siz)
var node = document.getElementById("div_editable");
node.lastChild.focus();
var textNode = node.lastChild;
var caret = siz;
var range = document.createRange();
range.setStart(textNode, node.lastChild.innerText.length);
range.setEnd(textNode, node.lastChild.innerText.length);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
&#13;
.highlight {
background-color: red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="div_editable" style="min-width: 320px; min-height: 120px" contenteditable="true">Use this place</div>
&#13;
正如您所看到的,将背景颜色应用于额外的文本是有效的!
我的问题是,一旦它达到60个字符,光标或插入符号就会向后移动开始,插入符号仍在那里并且永远不会扩展。
答案 0 :(得分:2)
想要将60后的div的文本颜色更改为红色。相似 喜欢twitter
当然,这很棘手。只要您只想在指定长度(在您的情况下为60)后更改文本的颜色,您尝试的任何内容都足够好。只需将超出的字符包装在另一个元素中,就可以应用合适的类。
您的代码没有问题,而且您肯定是在正确的轨道上。
您的问题:
但是,当您希望动态调整时,棘手就会开始复合。即继续在任何地方打字,并在旅途中突出显示额外的文字。
您遇到的问题是保持光标位置不变!
<强>原因强>:
对于contenteditable本身中的每个元素节点,contenteditable
选择范围和偏移重新开始。而这些仅适用于文本节点。这意味着,如果在您的contenteditable div中有另一个元素,那么光标位置将从该元素内偏移。
当您将超出的文本包装到span
以突出显示那些文本时,这表现在您的情况中。在div
中包含额外文本后覆盖span
的内容后,您将使用其文本节点的上下文丢失光标位置。
<强>解决方案强>:
之前,进行任何更改都会缓存当前光标位置以及文本节点光标所在。然后,在进行更改后(将更多文本包装在另一个元素和其他内容中),请使用{{ 1}}和range.setStart
在该节点的range.setEnd
上,因为它将是您可以使用光标的文本节点。
您可以使用firstChild
对象的anchorNode
找到当前节点。这将返回光标当前所在的文本节点。为了稍后在脚本中使用它,可以使用selection
来获取其父元素。然后可以在将光标设置回来时使用此元素。在下面的示例中,我使用parentNode
标记(,如Twitter ),然后通过选择em
来获取实际文本节点。如果光标位于前60个字符区域,那么您将获得firstChild
contenteditable
而不是div
。
以下是一个粗略的示例摘录: (适用于Chrome,未经其他浏览器测试)
请注意,您现在可以从任何地方开始输入并保留光标。
em
var div = document.querySelector('div[contenteditable]'), allowedSize = 60;
reformat(div);
div.addEventListener('keyup', highlight);
function highlight(e) { reformat(e.target); }
function reformat(elem) {
var size = elem.textContent.length,
wrapper, txt, firstSection, nextSection, cursorPos
;
cursorPos = getCursorPosition();
elem.dataset.size = allowedSize - size;
if (size > allowedSize) {
txt = elem.textContent;
wrapper = document.createElement('em');
firstSection = txt.slice(0, allowedSize);
nextSection = txt.slice(allowedSize);
wrapper.textContent = nextSection;
elem.innerHTML = firstSection;
elem.appendChild(wrapper);
if (cursorPos) { setCursorPosition(cursorPos) }
}
}
function getCursorPosition() {
var retVal = {};
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount > 0) {
retVal.node = sel.anchorNode.parentNode;
retVal.pos = sel.getRangeAt(0).startOffset;
return retVal;
}
}
return null;
}
function setCursorPosition(position) {
var textNode, range, sel;
if (position.node.tagName == 'EM') {
textNode = div.getElementsByTagName('EM')[0].firstChild;
} else {
if (position.pos > allowedSize) {
textNode = div.getElementsByTagName('EM')[0].firstChild;
position.pos = 1;
} else { textNode = position.node.firstChild; }
}
range = document.createRange();
range.setStart(textNode, position.pos);
range.setEnd(textNode, position.pos);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
div[contenteditable] {
position: relative;
width: 70vw; height: 120px; padding: 4px;
margin: 8px auto; border: 1px solid #bbb;
font-family: sans-serif; outline: none;
}
div[contenteditable]::after {
content: attr(data-size);
position: absolute; top: 105%; right: 0;
}
div[contenteditable] em { background-color: #fcc; }
小提琴:https://jsfiddle.net/abhitalks/rmprz6rx/ ;给你玩。
注意:以上示例是粗略的尝试。为了让它跨浏览器和抛光扭结,留给读者练习。
答案 1 :(得分:0)
如果要更改输入的文本颜色。请遵循以下代码
$('input').keypress(function(){
var len=$('input').val().length;
if(len>60)
{
$('input').css('color','red')
}
})
由于