Using mouse cursor position as a range starting po

2019-08-29 09:53发布

As the title states, I would like to use my cursor's position as the start point to a range.

Right now have simple sample like this

<html>
  .
  .
   <p>The quick brown fox jumps over the lazy dog</p>
  .
  .
</html>

On the CS/JS side of things I have event listen set to mouse move that attempts to print out the offset for the cursor position, however I am not using the correct method and end up getting either undefined or no method errors.

Again, really simple CS for the time being since I really just wanted to test it out.

$(document).ready ->

  $(document).mousemove ->
    target = event.target
    console.log("#{target.offset()}") // also tried .rangeOffset .offset

Ideally I would like something that I can input into a range.setStart() function.

For example, if I was to be moused over the f in fox I would want the offset to be return as 16 so that I may then set the start of the range like so range.setStart(target,16).

Any help setting me in the right direction would be greatly appreciated.

edit: After typing this up and submitting it I realized how silly it was to expect the element to give me back offset information. I am terribly lost, please guide me.

2条回答
迷人小祖宗
2楼-- · 2019-08-29 10:29

You should be using pageX or pageY, like this

$(document).ready ->

  $(document).mousemove (e) ->
    console.log("#{e.pageX}")
    console.log("#{e.pageY}")

If you need to get the position relative to a div for example

$(document).ready ->

      $(document).mousemove (e) ->
        console.log("#{e.pageX - $('#divID').offset().left}")
        console.log("#{e.pageY - $('#divID').offset().top}")

Applied to your case, it would give you something like this

$(document).ready ->

  $('p').mousemove (e) ->
    console.log("#{e.pageX - $('p').offset().left}")
    console.log("#{e.pageY - $('p').offset().top}")

And moving your mouse over the paragraph containing your text will give you your mouse position inside the paragraph

see it working here http://jsfiddle.net/zXnk9/


EDIT

If you need to get the index of the character you are hovering you could use a trick like so:

Wrap your text inside a container that is exactly the width of your text

<span>The quick brown fox jumps over the lazy dog</span>

And then make the following calculation

$(document).ready ->
  // define the container for the text you are intersted in
  container = $('span')
  // on mouseover
  container.mouseover (e) ->
    // get container width
    container_width = container.width()
    // compute the avg character width base on the container width and the number of characters contained in your text. 
    // (If you have some complex formatting inside your container, you would have to adjust this calculation.)
    char_width = p_width / container.text().length
    // get the position of your mouse inside
    position_inside = e.pageX - container.offset().left
    // define the index of the character you are interested in
    char_index = Math.floor(position_inside / char_width) - 1
    // use it as you wish
    // print it for example
    console.log("#{char_index}")

You can check it working here. I've set the event to click so that you can try it precisely on the f of fox, it returns 16. http://jsfiddle.net/zXnk9/1/

EDIT 2: for a reliable way of doing what you are trying to do

When loading the document, put every character inside the container into an html node, like this

$(document).ready ->
  // set your container
  container = $('span')

  // define a replacement text string
  replacement_container_text = ''
  // iterate over each character inside your container
  $(container.text().split('')).each (i, char) ->
    // put it inside a span and add it to your replacement text string
    replacement_container_text += '<span>' + char + '</span>'

  // set the replacement text string as the html content of your container
  // this replaces the original text with the initial text with each 
  // character wrapped into a span 
  // (which can then be caught as targets for your mousemove events)
  container.html(replacement_container_text)   

Then you can just get the index of the character on which your mouse is positionned with the following

container.mousemove (e) ->
  range_start = container.children('span').index $(e.target)
  console.log(range_start)

This will work with multi line containers, with paragraphs, etc.

See working example http://jsfiddle.net/2TBFV/

查看更多
叼着烟拽天下
3楼-- · 2019-08-29 10:36

After much googling and many hours of troubleshooting I finally came up with a solution that works for my purposes.

The function document.caretPositionFromPoint() or for Webkit document.caretRangeFromPoint() takes X and Y coordinates from an event and returns a caret position that I can then use to create the start point of my range with.

$(document).ready ->

  setRange = (event) ->
      if document.caretPositionFromPoint
        #for Firefox
      else if document.caretRangeFromPoint
        range = document.caretRangeFromPoint(event.pageX, event.pageY)
        targetNode = range.startContainer
        offset = range.startOffset
        range.setStart(targetNode, offset)
        range.setEnd(targetNode, 10) #just to test

        sel = window.getSelection()
        sel.removeAllRanges()
        sel.addRange(range)

    element = document.getElementById("content")
    element.addEventListener('mousemove', setRange, true) #eventlistener instead of .mousemove for event bubbling
查看更多
登录 后发表回答