6

Assuming there is a mousestop event attached to the entire document, what is the best way to figure out the exact word under the cursor (if there is any text), when the mouse stops moving?

I can get the underlying (jQuery) element from the event handler - $(document.elementFromPoint(e.clientX, e.clientY)) - but then what is next?

So far my idea is to replace all text nodes within hit element with their copy where each word is wrapped in a DOM element (don't know which one yet) and then call $(document.elementFromPoint(e.clientX, e.clientY)) again to get the element that contains only the word under mouse.
But that seems like a complicated plan and I wonder whether I am missing something simpler.

artemave
  • 6,786
  • 7
  • 47
  • 71
  • 1
    The answers from [ **the other question** ](http://stackoverflow.com/questions/2444430/how-to-get-a-word-under-cursor-using-javascript) basically do what you suggest in the question... they just wrap each word in its own element, and from there it's not too hard... - There are issues with how to do this while preserving existing styling of text. – Peter Ajtai Oct 04 '10 at 19:37
  • @Peter: there is a very neat solution to the styling issue - make up your own element. – artemave Oct 04 '10 at 22:05

2 Answers2

2

Well, no magic tricks so far, so here is the dull boring (and yet working) solution:

  $(document.body).mousemove(function(e){

    var onmousestop = function() {
      function getHitWord(hit_elem) {
        var hit_word = '';
        hit_elem = $(hit_elem);

        //text contents of hit element
        var text_nodes = hit_elem.contents().filter(function(){
          return this.nodeType == Node.TEXT_NODE && this.nodeValue.match(/[a-zA-Z]{2,}/)
        });

        //bunch of text under cursor? break it into words
        if (text_nodes.length > 0) {
          var original_content = hit_elem.clone();

          //wrap every word in every node in a dom element
          text_nodes.replaceWith(function(i) {
            return $(this).text().replace(/([a-zA-Z-]*)/g, "<word>$1</word>")
          });

          //get the exact word under cursor
          var hit_word_elem = document.elementFromPoint(e.clientX, e.clientY);

          if (hit_word_elem.nodeName != 'WORD') {
            console.log("missed!");
          }
          else  {
            hit_word = $(hit_word_elem).text();
            console.log("got it: "+hit_word);
          }

          hit_elem.replaceWith(original_content);
        }

        return hit_word;
      }

      var hit_word = getHitWord(document.elementFromPoint(e.clientX, e.clientY));
      ...
    }
  }

There are few other subtleties involved (like event 'noise reduction', keeping replaced dom context (such as selection) and so forth), but you get the idea.

Here you can learn how set up mousestop event.

EDIT:

Making custom html elements may not be that strait forward in IE (who would have thought?). Check out more here.

Community
  • 1
  • 1
artemave
  • 6,786
  • 7
  • 47
  • 71
  • I tried wrapping every text element in the tags beforehand, but this caused a bad performance on iPhone 3GS (with much text). So, instead am trying your technique to temporarily replace the words with the tags at the time of the hit test... – Rick Love May 16 '12 at 09:50
1

I don't have any code for you, but perhaps this may be of a little help:

  1. When cursor is Idle, get coordinates
  2. Search for elements within the page at the above coordinate
  3. Use something like var s = getElementById('ElementIDFoundinStepAbove').innerHTML;

That seems like a fairly logical approach, however, I don't know if this is at all possible.


Edit:

I have just found this post on S/O:

2444430

I hope this helps.

:)

Jason

Community
  • 1
  • 1