如何用当前光标位置的单击元素替换字符?

时间:2019-06-27 12:40:34

标签: javascript jquery

我有一个内容可编辑的div,当您键入@时,列表就会出现。现在,我希望能够在contenteditable div中的当前光标位置单击li元素时插入一些文本。我不知何故需要找到光标位置,并用一些文本替换@。假设我输入“ Javascript is @”以产生“ Javascript is awesome”。

$('.reply').on('keydown', function(e) {
  if (e.keyCode == 86) {
    $('.list').show();
  } else {
    $('.list').hide();
  }
})
.list {
  display: none;
}

.reply {
  border: 1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reply" contentEditable="true"></div>
<ul class="list">
  <li>One</li>
  <li>Two</li>
  <li>three</li>
  <li>Four</li>
  <li>Five</li>
</ul>

2 个答案:

答案 0 :(得分:3)

如果要检测用户是否按 @ 键,除了检查单个keyCode之外,还需要检查 alt 键是否也按下。

$('.reply').on('keydown', function(e) {
  if (e.altKey && e.keyCode == 81) {
    $('.list').show();
  } else {
    $('.list').hide();
  }
});

要在单击时获取li元素的内容,您需要将click事件侦听器附加到列表,并使用 e.target.firstChild.data 在回调函数中检索文本。 >

现在,事情变得有些棘手了,因为您使用的是内容可编辑的 div 而不是 textarea 。 div不提供内置方法来检索光标的位置,因此我们需要使用 Selection API自行实现。

首先将两个新属性添加到HTML div元素

HTMLDivElement.prototype.selectionStart = 0;
HTMLDivElement.prototype.selectionEnd = 0;

并将多个侦听器附加到div元素,以检查是否有内容写入

['mousedown', 'mouseup', 'keydown', 'keyup'].forEach(function(evt) {
  document.getElementsByClassName("reply")[0].addEventListener(evt, update);
});

以防万一-相应地更新新属性

function update(e) {
  var caret = window.getSelection().anchorOffset;
  e.target.selectionStart = caret;
  e.target.selectionEnd = caret + window.getSelection().focusOffset;
}

现在,事情变得简单,只需检索li元素的click事件处理程序内的光标位置,然后减去1并用适当的文本替换内容即可。

这是一个例子:

HTMLDivElement.prototype.selectionStart = 0;
HTMLDivElement.prototype.selectionEnd = 0;

function update(e) {
  var caret = window.getSelection().anchorOffset;
  e.target.selectionStart = caret;
  e.target.selectionEnd = caret + window.getSelection().focusOffset;
}

['mousedown', 'mouseup', 'keydown', 'keyup'].forEach(function(evt) {
  document.getElementsByClassName("reply")[0].addEventListener(evt, update);
});

$('.reply').on('keydown', function(e) {
  if (e.altKey && e.keyCode == 81) {
    $('.list').show();
  } else {
    $('.list').hide();
  }
});



$('.list').on('click', function(e) {
  var text = $('.reply').text();
  var pos = $('.reply')[0].selectionStart - 1;
  text = text.substring(0, pos) + e.target.firstChild.data + text.substring(pos + 1);
  $('.reply').text(text);
});

$('.list').hide();
.reply {
  border: 1px solid #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reply" contentEditable="true">

</div>

<ul class="list">
  <li>One</li>
  <li>Two</li>
  <li>three</li>
  <li>Four</li>
  <li>Five</li>
</ul>

答案 1 :(得分:1)

您必须像这样将事件添加到列表中。

$('.list li').bind('click', function(){
    var inputValue = $(".reply").text();
  var indexOfAt = inputValue.indexOf('@');

  if(indexOfAt != -1){
    var modifiedText = $(".reply").text().replace('@',$(this).text());
    $(".reply").text(modifiedText);
  }
  $('.list').hide();
});