如何使用js

时间:2017-03-07 04:01:01

标签: javascript jquery css

制作像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;
&#13;
&#13;

正如您所看到的,将背景颜色应用于额外的文本是有效的!

我的问题是,一旦它达到60个字符,光标或插入符号就会向后移动开始,插入符号仍在那里并且永远不会扩展。

2 个答案:

答案 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')
    }
})

由于