Contenteditable显示上次插入的html元素

时间:2018-01-12 10:23:36

标签: jquery html css contenteditable

我使用一个contenteditable div作为输入字段来键入一些文本,并通过该文本中的按钮(小html图片)插入图标。

只要文字比可满足的字段更窄,就可以了。

一旦文字长于字段(因此它被部分隐藏):

当我输入一个文字字符时,一切都很好,按下该键后会自动显示最后一个字符,这样您就可以随时看到您输入的内容。 但是当我通过按钮输入一个图标时,图标就可以了,但它被隐藏,因为字段内容不会移动以使新输入的图标可见,直到我输入另一个文本字符。

对此的任何解决方案,以便输入的最后一个元素(文本或html)始终对用户可见?

function pasteIcon(html) {
  var sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();
      var el = document.createElement("div");
      el.innerHTML = html;
      var frag = document.createDocumentFragment(),
        node, lastNode;
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      range.insertNode(frag);
      if (lastNode) {
        range = range.cloneRange();
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  } else if (document.selection && document.selection.type != "Control") {
    document.selection.createRange().pasteIcon(html);
  }
}

$(document).ready(function() {
  $('.buttOn').click(function() {
    $('.contEd').focus();
    pasteIcon('<img class="icOn" src="http://www.bmgstuff.com/files/interface/generator_frame/text_blood.png">');
  })
});
[contenteditable="true"] {
  display: inline;
  white-space: nowrap;
  overflow: hidden !important;
  text-overflow: inherit;
  -webkit-user-select: text !important;
  -moz-user-select: text !important;
  -ms-user-select: text !important;
  user-select: text !important;
}

[contenteditable="true"] br {
  display: none;
}

.contAiner {
  display: flex;
}

.buttOn {
  width: 24px;
  height: 24px;
  border: none;
  background: #666;
  color: white;
}

.contEd {
  height: 22px;
  text-align: center;
  width: 100px;
  line-height: 23px;
  color: black;
  font-size: 10.5px;
  font-family: arial;
  border: 1px solid black;
}

.icOn {
  width: 9px;
  height: 13px;
  top: 1px;
  position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="contAiner">
  <input class="buttOn" type="button" value="B">
  <div class="contEd" contenteditable="true" spellcheck="false" autocomplete="off"></div>
</div>

以下是jsFiddle

以下是original thread我从中获取了“pasteIcon”函数。

PS:我试图在pasteIcon函数之后触发一个键码39(右箭头),以便模拟按键,但它只是不起作用。

1 个答案:

答案 0 :(得分:5)

您只需将编辑器滚动到插入的图标即可。移动选择后,请注意两行代码。希望它按预期工作:)

更新:

为了涵盖所有情况,我们需要检查插入的图像是否在编辑器范围之内或之外。 首先,让我们在编辑器元素中添加id,以便更容易找到它。然后我们可以利用函数getBoundingClientRect在屏幕上返回一个实际元素的矩形。最后,我们比较矩形,如果图像矩形不在编辑器内(imgRect.left&lt; editorRect.left || imgRect.right&gt; editorRect.right),那么我们滚动。

更新2:

在调查最新评论中描述的问题时,我发现在经过一定长度的编辑内容后,jQuery函数'offset'会返回不准确的结果。最有可能的原因是,编辑器的leftOffset在这种情况下不会自动更新。 最后,我将所需的滚动位置计算更改为图像DOM元素的offsetLeft减去编辑元素的offsetLeft减去1(边框大小),现在它可以在任何内容长度下正常工作。

function pasteIcon(html) {
  var sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();
      var el = document.createElement("div");
      el.innerHTML = html;
      var frag = document.createDocumentFragment(),
        node, lastNode;
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      range.insertNode(frag);
      if (lastNode) {
        range = range.cloneRange();
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);

   	    var editorRect = $(contEdit)[0].getBoundingClientRect();
       	var imgRect = $(lastNode)[0].getBoundingClientRect();
       	if (imgRect.left < editorRect.left || imgRect.right > editorRect.right) {
          var actualLeft = $(lastNode)[0].offsetLeft - editorRect.left - 1;
          $(".contEd").scrollLeft(actualLeft);
        }
      }
    }
  } else if (document.selection && document.selection.type != "Control") {
    document.selection.createRange().pasteIcon(html);
  }
}

$(document).ready(function() {
  $('.buttOn').click(function() {
    $('.contEd').focus();
    pasteIcon('<img class="icOn" src="http://www.bmgstuff.com/files/interface/generator_frame/text_blood.png">');
  })
});
[contenteditable="true"] {
  display: inline;
  white-space: nowrap;
  overflow: hidden !important;
  text-overflow: inherit;
  -webkit-user-select: text !important;
  -moz-user-select: text !important;
  -ms-user-select: text !important;
  user-select: text !important;
}

[contenteditable="true"] br {
  display: none;
}

.contAiner {
  display: flex;
}

.buttOn {
  width: 24px;
  height: 24px;
  border: none;
  background: #666;
  color: white;
}

.contEd {
  height: 22px;
  text-align: center;
  width: 100px;
  line-height: 23px;
  color: black;
  font-size: 10.5px;
  font-family: arial;
  border: 1px solid black;
}

.icOn {
  width: 9px;
  height: 13px;
  top: 1px;
  position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="contAiner">
  <input class="buttOn" type="button" value="B">
  <div id="contEdit" class="contEd" contenteditable="true" spellcheck="false" autocomplete="off"></div>
</div>