如何在contenteditable div中检测光标位置并在该位置插入文本

时间:2019-06-25 16:29:42

标签: javascript jquery coffeescript

我正在使用咖啡脚本,并且试图在内容可编辑div中的光标位置插入文本。我正在使用Tim Dowan函数来获取光标位置。每次div光标位置中的某个类型发生变化时,但是我不确定如何更新updateTextArea函数中的变量,运行该函数时我会得到相同的光标位置。有更好的方法吗?

# Get curret position in Content Editable div
getSelectionCharacterOffsetWithin = (element) ->
  start = 0
  end = 0
  doc = element.ownerDocument or element.document
  win = doc.defaultView or doc.parentWindow
  sel = undefined
  if typeof win.getSelection != 'undefined'
    sel = win.getSelection()
    if sel.rangeCount > 0
      range = win.getSelection().getRangeAt(0)
      preCaretRange = range.cloneRange()
      preCaretRange.selectNodeContents element
      preCaretRange.setEnd range.startContainer, range.startOffset
      start = preCaretRange.toString().length
      preCaretRange.setEnd range.endContainer, range.endOffset
      end = preCaretRange.toString().length
  else if (sel = doc.selection) and sel.type != 'Control'
    textRange = sel.createRange()
    preCaretTextRange = doc.body.createTextRange()
    preCaretTextRange.moveToElementText element
    preCaretTextRange.setEndPoint 'EndToStart', textRange
    start = preCaretTextRange.text.length
    preCaretTextRange.setEndPoint 'EndToEnd', textRange
    end = preCaretTextRange.text.length
  {
    start: start
    end: end
  }

$(document).on 'input', '.reply-area', (e) ->
    currentElement = e.target

    reportSelection = (element) ->
      selOffsets = getSelectionCharacterOffsetWithin(element)
      return selOffsets.start

    currentCursorPosition = reportSelection(currentElement)

    updateTextArea = (element) ->
      # Get clicked user email
      thread_user_email = element.querySelector('.thread-user-email').textContent

      # Get element
      elementToInsert = $(currentElement).html()

      # Cursor position, email to insert, Text before cursor and text after cursor
      splitIndex = currentCursorPosition
      sliceIndex = currentCursorPosition - 1
      sliceString = elementToInsert.slice(sliceIndex, splitIndex)
      beforeString = elementToInsert.substring(0, sliceIndex)
      afterString = elementToInsert.substring(splitIndex)
      emailToInsert = '+' + thread_user_email + ' '     

      # Updated reply, comment text
      $(currentElement).html(beforeString + emailToInsert + afterString)

      # Hide the list
      $(thread_users_list).hide()

    $('.thread-users-list li').click (e) ->
        e.stopImmediatePropagation()
        updateTextArea(this)

1 个答案:

答案 0 :(得分:0)

尽管您看不到您要更改的HTML,但很难猜到,但是我发现您的代码有一些小问题。

在CoffeeScript中,函数的缩进很重要,因此您要确保所有内容都正确对齐。其次,您应该能够创建一个窗口级var来存储光标位置,然后您就可以在代码中的任何位置访问该光标位置。这是您的代码的更新版本,该代码在本地对我有效,并有一些内联注释:

window.currentCursorPosition = null

# Get curret position in Content Editable div
getSelectionCharacterOffsetWithin = (element) ->
  ...
  ...

# You can simplify this quite a bit
$(document).on 'input', '.reply-area', (e) ->
  window.currentCursorPosition = getSelectionCharacterOffsetWithin(e.target).start

# Make sure this is not indented below $(document) code
updateTextArea = (element) ->
  ...
  ...

# Make sure this is not indented below $(document) code
$('.thread-users-list li').click (e) ->
    e.stopImmediatePropagation()
    updateTextArea(this)