12

I am building a WYSIWYG rich text editor.

When the user selects a portion of his/her text, I would like to present a menu in a tooltip. Presenting the menu works fine but I would like to only show it if the user hovers over the selected text.

As Illustrated:

enter image description here

I also haven't decided on positioning (I like the way that it's illustrated) but to clarify, that's not the point of the question.

The question is: How do I filter for a hover event that happens over selected text?

The Problems:

  1. I can't just listen for a text selection event or test hover events to see whether they are over elements that have selected text inside them. The left image would generate a false positive with that.

  2. I know how to get the selected text but I don't know how to get the selected region.

To my mind, the ideal solution is somehow to calculate the region of the selected text and test whether mouseover events happen in that region.

jcuenod
  • 55,835
  • 14
  • 65
  • 102
  • http://stackoverflow.com/questions/5379120/get-the-highlighted-selected-text Does this help? – ggzone Jun 02 '15 at 15:03
  • That only gets the selected text: I actually need some way to get the region on the screen that the browser has drawn on. – jcuenod Jun 02 '15 at 15:05
  • 1
    May be you could wrap the selected text in a tag and bind hover to that specific tag? – lshettyl Jun 02 '15 at 15:13
  • @LShetty not a bad idea, I was hoping for a more elegant solution. That will probably mean artificially reselecting the text and may run into problems when the selection is modified with the keyboard. Not sure, would have to experiment. – jcuenod Jun 02 '15 at 15:20
  • @LShetty also problems arise when part of the selection is over styled text - the html becomes invalid `hello world lorem` – jcuenod Jun 02 '15 at 15:23
  • I have failed to compile an answer for you. Check out: http://jsfiddle.net/tomt5tkj/ - When the text has been selected, it wraps it around in a `span`-tag, which then gets an id. The code was gathered from StackOverflow somewhere. I take no credit! – MortenMoulder Jun 02 '15 at 15:23

2 Answers2

6

On mouseup, use Range.getClientRects to grab the bounding rectangles of each line of the selection.

You can then test if the mouse is over the selection like this:

var cr= [];

$(document).on({
  'mouseup': function() {
    cr= window.getSelection().getRangeAt(0).getClientRects();
  },
  'mousemove': function(ev) {
    //hide the pop up
    for(var i = 0 ; i < cr.length ; i++) {
      if(ev.pageX >= cr[i].left && ev.pageX <= cr[i].right &&
         ev.pageY >= cr[i].top  && ev.pageY <= cr[i].bottom
        ) {
        //show the pop up
        break;
      }
    }
  }
});

Fiddle

Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79
2

Try this way:

JS

$(document).ready(function () {
    $(document).on("mouseup", ".conttext", function () {
        var highlight = window.getSelection();
        console.log(highlight);
        var spn = '<span class="highlight">' + highlight + '</span>';
        var text = $('.conttext').text();
        $('.conttext').html(text.replace(highlight, spn));
    });
    $(document).on("mouseover", ".highlight", function () {
        alert("You hovered on selected tex"); // Your tooltip code goes here
    })
});

CSS:

.highlight {
    color:#888;
    position:relative;/*This will not matter if you inject tooltip using JS*/
    display:inline-block;/*This will not matter if you inject tooltip using JS*/
}

HTML:

<div class="conttext">Sample text</div>

Demo: http://jsfiddle.net/lotusgodkk/BGKSN/202/

K K
  • 17,794
  • 4
  • 30
  • 39
  • What about a case like `hello world lorem`? (considering the point is WYSIWYG editing) – jcuenod Jun 02 '15 at 15:26
  • In that case, you may refer to this solution: http://stackoverflow.com/questions/2139616/window-getselection-gives-me-the-selected-text-but-i-want-the-html . You mentioned only text in the post and I considered text in the solution. However, this solution can help you in modifying or updating your code. – K K Jun 02 '15 at 15:31
  • This code does not preserve the caret position after text replacement. – maswerdna Jun 12 '19 at 17:19