views:

6501

answers:

10

I would like to have users click a link that then selects the html text in another element (NOT an input). By "select" I mean the same way you would select text by dragging your mouse over it. This has been a bear to research because everyone talks about "select" or "highlight" in other terms.

Is this possible?

My code so far is thus:

html:

<a href="javascript:" onclick="SelectText('xhtml-code')">Select Code</a>
<code id="xhtml-code">Some Code here </code>

js (jquery):

function SelectText(element) {
    $("#" + element).select();
}

but it doesn't work. Am I missing something blatantly obvious?

Thanks

+1  A: 

Have a look at the Selection object (Gecko engine) and the TextRange object (Trident engine.) I don't know about any JavaScript frameworks that have cross-browser support for this implemented, but I've never looked for it either, so it's possible that even jQuery has it.

Blixt
A: 

According to the jQuery documentation of select():

Trigger the select event of each matched element. This causes all of the functions that have been bound to that select event to be executed, and calls the browser's default select action on the matching element(s).

There is your explanation why select() won't work in this case.

I think should approach it slightly differently. You could try placing a span tag around the text you want to highlight and give that span an appropriate css style.

Kees de Kooter
i'm not trying to highlight the text with a css style. i want the text to be selected.
Jason
Sorry. Guess I misread your question.
Kees de Kooter
+2  A: 

This thread contains really wonderful stuff. But I'm not able to do it right on this page using FF 3.5b99 + FireBug due to "Security Error".

Yipee!! I was able to select whole right hand sidebar with this code hope it helps you:

    var r = document.createRange();
    var w=document.getElementById("sidebar");  
    r.selectNodeContents(w);  
    var sel=window.getSelection(); 
    sel.removeAllRanges(); 
    sel.addRange(r);

PS:- I was not able to use objects returned by jquery selectors like

   var w=$("div.welovestackoverflow",$("div.sidebar"));

   //this throws **security exception**

   r.selectNodeContents(w);
TheVillageIdiot
You need to get the element from jQuery, as you're trying to select a jQuery object: var w=$("div.welovestackoverflow",$("div.sidebar")).get(0);
Blixt
doesn't work... i get an error "object does not support this method" and it highlights the first line. i did some digging and found that there's a "document.body.createTextRange()" but then "selectNodeContents" doesn't work.... and this is in IE
Jason
i read that thread you found... amazing... i was able to create a function from that info that works on all browsers.Thank you so much! My solution is posted
Jason
+12  A: 

I have found a solution for this, thanks to this thread found by TheVillageIdiot. I was able to modify the info given and mix it with a bit of jQuery to create a totally awesome function to select the text in any element, regardless of browser:

function SelectText(element) {
    var text = document.getElementById(element);
    if ($.browser.msie) {
        var range = document.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = window.getSelection();
        selection.setBaseAndExtent(text, 0, text, 1);
    }
}
Jason
note: this works with jQuery 1.3.2... not sure if it will work in 1.4.x
Jason
+1  A: 

jason almost has it with his selectText function. avoid browser detection and it might just be the next masterpiece.

someone
unfortunately, there's no way around browser detection... each browser handles selection differently :\
Jason
Jason: not true. There's IE and non-IE (apart from Safari pre-version 3, which is not too common these days), and you can directly the features you need rather than rely on browser sniffing.
Tim Down
A: 

Jason's code can not be used for elements inside an iframe (as the scope differs from window and document). I fixed that problem and I modified it in order to be used as any other jQuery plugin (chainable):

Example 1: Selection of all text inside < code > tags with single click and add class "selected":

$(function() {
    $("code").click(function() {
        $(this).selText().addClass("selected");
    });
});

Example 2: On button click, select an element inside an Iframe:

$(function() {
    $("button").click(function() {
        $("iframe").contents().find("#selectme").selText();
    });
});

Note: remember that the iframe source should reside in the same domain to prevent security errors.

jQuery Plugin:

jQuery.fn.selText = function() {
    var obj = this[0];
    if ($.browser.msie) {
        var range = obj.offsetParent.createTextRange();
        range.moveToElementText(obj);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        var range = obj.ownerDocument.createRange();
        range.selectNodeContents(obj);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        selection.setBaseAndExtent(obj, 0, obj, 1);
    }
    return this;
}

I tested it in IE8, Firefox, Opera, Safari, Chrome (current versions). I'm not sure if it works in older IE versions (sincerely I don't care).

lepe
+7  A: 

Here's a version with no browser sniffing and no reliance on jQuery:

function selectElementText(el, win) {
    win = win || window;
    var doc = win.document, sel, range;
    if (win.getSelection && doc.createRange) {
        sel = win.getSelection();
        range = doc.createRange();
        range.selectNodeContents(el);
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (doc.body.createTextRange) {
        range = doc.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
}

selectElementText(document.getElementById("someElement"));
selectElementText(elementInIframe, iframe.contentWindow);
Tim Down
Thanks Tim, I had to add el.focus(); to the top of the function. Maybe it's only required when the function is triggered from clicking on certain elements in certain browsers. For me, a button element in FF 3.6
Luckyrat
A: 

When I try your selectElement function, I get a JS error about "text is undefinited". I see you have a function that accepts "text" as a variable, but that varaible isn't definted or set anywhere else. Are you missing a line?

Harold Blackorby
A: 

Tim's method works perfectly for my case - selecting the text in a div for both IE and FF after I replaced the following statement:

range.moveToElementText(text);

with the following:

range.moveToElementText(el);

The text in the div is selected by clicking it with the following jQuery function:

        $(function () {
        $("#divFoo").click(function () {
             selectElementText(document.getElementById("divFoo"));
        })
     });
Hong
Ah yes. Thanks for spotting that. I've edited my answer.
Tim Down
A: 

I have found this jQuery plugin to be extremely useful!

http://plugins.jquery.com/node/7411

dennismonsewicz