简体   繁体   中英

How to detect cursor position in contenteditable div and insert text at that position

I'm using coffee script and I'm trying to insert text at cursor position in content editable div. I'm using Tim Dowan function to get the cursor position. Everytime a type something in a div cursor position changes but I'm not sure how to update variable in updateTextArea function, I'm getting the same cursor position when i run the function. Is there a better approach for this?

# 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)

Although without seeing the HTML you're trying to alter it's hard to guess, I can see a few little issues with your code.

In CoffeeScript, the indentations of your functions matter, so you want to make sure everything is lined up correctly. Second, you should be able to create a window-level var to store the cursor position that you can then access anywhere in your code. Here's an updated version of your code that worked locally for me with some comments inline:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM