18

I am trying to learn how to write a bookmarklet where I can highlight some text, click on the bookmarklet and have it tell me what got highlighted. I can get that far, but next I want to know what element that text is in.

For example:

<div id="some-id">to be highlighted</div>

The bookmarklet code:

javascript:(function(){alert(window.getSelection();})()

If I highlight the text "to be highlighted" and then click on the bookmarklet, it will alert the text. But how can I get the element in which the text is in, in this case the element after that?

So the flow is: highlight text, click bookmarklet, bookmarklet tells you what you highlighted and the element it's in.

Thanks!

Koes Bong
  • 1,113
  • 3
  • 15
  • 28
  • Not to be an obscene spammer or anything, but I recently wrote a [bookmarklet generator](http://zbooks.zzzzbov.com/) that throws jQuery on the page and allows you to write your bookmarklet in an external script. I don't mind if you [examine the code being executed](http://zbooks.zzzzbov.com/assets/js/zbooks-1.1.js) either. – zzzzBov Jan 09 '11 at 00:43

3 Answers3

33

Try something similar to this to get the dom element that contains the selected text.

window.getSelection().anchorNode.parentNode

It works on firefox and Chrome, you should test it into the remaining browsers.

It have a quirk, if you select text that beholds to more than an element, only the first one is returned. But maybe you can live with this.

Just for reference on what is the anchorNode property: http://help.dottoro.com/ljkstboe.php

On internet explorer this snippet should do the trick (I can't test it)

document.selection.createRange().parentElement();

as stated into http://msdn.microsoft.com/en-us/library/ms535872.aspx and http://msdn.microsoft.com/en-us/library/ms536654.aspx

A range explanation on quirksmode: http://www.quirksmode.org/dom/range_intro.html

Eineki
  • 14,773
  • 6
  • 50
  • 59
11

You can do this relatively simply in all major browsers. Code is below, live example: http://jsfiddle.net/timdown/Q9VZT/

function getSelectionTextAndContainerElement() {
    var text = "", containerElement = null;
    if (typeof window.getSelection != "undefined") {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            var node = sel.getRangeAt(0).commonAncestorContainer;
            containerElement = node.nodeType == 1 ? node : node.parentNode;
            text = sel.toString();
        }
    } else if (typeof document.selection != "undefined" &&
               document.selection.type != "Control") {
        var textRange = document.selection.createRange();
        containerElement = textRange.parentElement();
        text = textRange.text;
    }
    return {
        text: text,
        containerElement: containerElement
    };
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
0

I don't think you can, he only way to know which element is currently being used would be to use a onclick event on the element. Other than that there is no sure way. You can however search each element until you find an element with the same text,

jQuery('*:contains(' + selected + ').

You can add an event to get the current element with this code though (untested)

var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++)
    all[i].onclick = function(e){
        window.selectedElement = all[i];
        //preventDefault $ StopBubble &
        return false;
    }

And it will be stored in selectedElement

Ok try This:

var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++)
    all[i].onclick = function(e) {
        window.selectedElement = this;
        ((e && e.stopPropagation && e.stopPropagation()) ||
         (window.event && (window.event.cancelBubble = true)));
        return false;
    }

DEMO: http://jsfiddle.net/HQC6Z/1/ Better yet: http://jsfiddle.net/HQC6Z/

After looking at the other answers, I take back my solution and offer theirs:

How can I get the element in which highlighted text is in?

How can I get the element in which highlighted text is in?

Community
  • 1
  • 1
qwertymk
  • 34,200
  • 28
  • 121
  • 184
  • Thanks. I don't think the first option of searching each element is feasible - especially with jQuery - since not all sites with have jQuery. So trying to do this with just pure JS. I tried the second solution and no luck. alerting (selectedElement) returns nothing. :-/ – Koes Bong Jan 09 '11 at 00:27
  • Thanks for the fiddle. But pardon my ignorance, but how exactly do I test that? I ran it and click on the list items and nothing happened. – Koes Bong Jan 09 '11 at 00:48
  • Try the second link, it's on jsFiddle which uses iframes so you can't really test it on their site, but you can see how to implement it based on the alert box, or try http://jsfiddle.net/HQC6Z/3/ with firebug – qwertymk Jan 09 '11 at 00:49
  • Got the second link to work. So clicking on the list items show the innerHTML, but how do I show what element it's in, or is that not possible as you mentioned? – Koes Bong Jan 09 '11 at 00:51
  • On jsFiddle it's not really possible but on your site this script should work – qwertymk Jan 09 '11 at 00:52
  • Awesome, tested it and got some results back. When I tried to alert(selectedElement) though, i get [object HTMLspanElement], instead of just span. How do I go inside the object and see what all is in there? – Koes Bong Jan 09 '11 at 01:05
  • 1
    This is brutal and highly inefficient, will break existing `click` event handlers, and won't work for selections selected via keyboard. You can get the selection text and the element containing the selection without needing any of this. See my answer. – Tim Down Jan 09 '11 at 01:49
  • Agreed, the other answer are better than mine. I can't delete it now that it's accepted though – qwertymk Jan 09 '11 at 01:50