5

What I'm really after is to detect when the cursor changes to type "text", that is, when I'm hover over a piece of text. I have tried looking at the element types I am hovering over, but this isn't too accurate because I don't know what they actually contain.

I understand that detecting the CSS cursor attribute is only possible if it has previously been assigned by me.

Is this possible at all? How would you go about doing this?

EDIT: I do not want to check If I am currently over a specific element, I want to know if I am hover over any text within that element. A div could be 100% width of the browser, but with a shorter piece of text at the far left. I don't want to detect when hovering over just any part of an element.

Challe
  • 866
  • 12
  • 26
  • 2
    I bet you'll get a better answer if you explain your use case. You may be looking at the problem the wrong way. – Wesley Murch Apr 30 '12 at 19:33
  • mouseover http://api.jquery.com/mouseover/ – Larry Battle Apr 30 '12 at 19:33
  • duplication : http://stackoverflow.com/questions/3395293/check-cursor-is-over-element – mgraph Apr 30 '12 at 19:34
  • @Madmartigan I simply want to be able to detect it, so that I then can do display this to the user, like changing the background-color of a div when any text is being hovered. – Challe Apr 30 '12 at 19:37
  • I'm sorry to say I don't believe this to be possible. You could theoretically find every text node on the page and wrap it in a span, then do something on hover of those spans. This is however horribly inefficient and changes the structure of the page. – James Montagne Apr 30 '12 at 19:45
  • Assuming `cursor` property isn't used to modify it, wouldn't it possible to watch for any change to `text` or `pointer` values? You'd "only" have to watch when the cursor moves (or when any event'd trigger a reflow, in case text would've move under the cursor) – FelipeAls Apr 30 '12 at 20:13
  • @FelipeAlsacreations But how do you detect at any given time which type of cursor you have? – James Montagne Apr 30 '12 at 20:23
  • @JamesMontagne Exactly, that's the problem. From what I understand, you can't detect the cursor property if it has not been set by your css. It will simply return "auto". – Challe Apr 30 '12 at 20:49

4 Answers4

1

No need to try to detect if the cursor changed.

You can simply detect if the mouse is hovering your text by using this kind of construct :

document.getElementById('myTextId').onmouseover = function() {
    // do something like for example change the class of a div to change its color :
    document.getElementById('myDivId').className = 'otherColor';
};

If you don't have an id but a class or a tag, you can replace getElementById by getElementsByClassName or getElementByTagName (which will return arrays on which you'll iterate).

If you want to restore the color when leaving the element, I suggest you bind the event onmouseout in the same way.

For example, if you want to do something on any paragraph, you may do that :

var paras = document.getElementByClassName('p');
for (var i=0; i<paras.length; i++) {
    paras[i].onmouseover = function() {
        // do something like for example change the class of a div to change its color :
        document.getElementById('myDivId').className = 'otherColor';
    };
}

I you plan to do a lot of things like this, I suggest you look at jquery and its tutorial.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 2
    I'm fairly certain this isn't what the question is asking for. There is no `id` or selector to use, he wants to detect whenever the cursor is over any "text". Sadly I don't think this is possible. – James Montagne Apr 30 '12 at 19:38
  • @JamesMontagne You're right, I'm sorry if I wasn't clear enough. – Challe Apr 30 '12 at 19:39
  • Any text, no. But that doesn't mean anything. So I suppose the need is for certain texts. That's the reason why I mentionned the searches by class or tag. Usually you'll have something like "

    " and you can use getElementsByClassName.

    – Denys Séguret Apr 30 '12 at 19:39
  • 1
    No, its for all TEXT_NODES, simply put, within all elements of a page. Like for example, when the mouse cursor changes to type text. – Challe Apr 30 '12 at 19:44
  • All text nodes : that would achieve nothing useful (look at your html, you have text nodes everywhere). Target something like the paragraphs or some classes. – Denys Séguret Apr 30 '12 at 19:47
0

One possible way is to find all the text nodes in your DOM and wrap them in a span with a certain class. Then you could select that class and do whatever you want with it:

// Wrap all text nodes in span tags with the class textNode
(function findTextNodes(current, callback) {
    for(var i = current.childNodes.length; i--;){
        var child = current.childNodes[i];
        if(3 === child.nodeType)
            callback(child);
        findTextNodes(child, callback);
    }
})(document.body, function(textNode){ // This callback musn't change the number of child nodes that the parent has. This one is safe:
    $(textNode).replaceWith('<span class="textNode">' + textNode.nodeValue + '</span>');
});

// Do something on hover on those span tags
$('.textNode').hover(function(){
    // Do whatever you want here
    $(this).css('color', '#F00'); 
},function(){
    // And here
    $(this).css('color', '#000');
});

JSFiddle Demo

Obviously this will fill your DOM with a lot of span tags, and you only want to do this once on page load, because if you run it again it will double the number of spans. This could also do weird things if you have custom css applied to spans already.

Paul
  • 139,544
  • 27
  • 275
  • 264
  • 1
    You'd better have a rock solid CSS reset to nuke any style that would apply to these `span` (nuke = inline style with `!important` at least) – FelipeAls Apr 30 '12 at 19:53
  • Basically what I was mentioning in the comments. This will basically work in general but is probably a really bad idea. I would really consider how important this feature is. – James Montagne Apr 30 '12 at 20:22
  • @JamesMontagne Yeah... I don't endorse this :P On non-minified HTML this will also create a ton of empty / whitespace filled span tags. As far as I'm aware this is the only way to accomplish it though, since you can't add events to text nodes. – Paul Apr 30 '12 at 21:13
0

This answer to another question gives a function to get a node from a point. Using this, you can just check if the mouse is over a text node's bounding boxes.

function isPointOverText(x, y) {
    const element = document.elementFromPoint(x, y);
    if (element == null) return false;
    const nodes = element.childNodes;
    for (let i = 0, node; (node = nodes[i++]); ) {
        if (node.nodeType === 3) {
            const range = document.createRange();
            range.selectNode(node);
            const rects = range.getClientRects();
            for (let j = 0, rect; (rect = rects[j++]); ) {
                if (
                    x > rect.left &&
                    x < rect.right &&
                    y > rect.top &&
                    y < rect.bottom
                ) {
                    if (node.nodeType === Node.TEXT_NODE) return true;
                }
            }
        }
    }
    return false;
}

window.addEventListener("mousemove", (e) => {
    console.log(isPointOverText(e.clientX, e.clientY))
})
hf02
  • 171
  • 2
  • 11
-1

If you're using jQuery (which you should, because jQuery is awesome), do this:

$("#myDiv").mouseover(function() {
    $("#myDiv").css("background-color", "#FF0000");
}); 
Daniel Bidulock
  • 2,344
  • 1
  • 26
  • 27
  • 2
    JQuery is okay if your new to javascript, but unnecessarily terrible for loading speed if you have already memorized all the cross-browser compatibility code. –  Apr 23 '17 at 21:51