Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts

    get user selected HTML text

    On IE you can use selection.createRange().htmlText to get the user selected HTML text. Other browsers like Safari and Firefox only have getSelection() which can only return unformated plain text, and there is nothing for HTML text.

    Does anyone have a method created to get user selected html text on all browsers?

    Thanks

  • #2
    New Coder
    Join Date
    Dec 2008
    Posts
    21
    Thanks
    0
    Thanked 3 Times in 3 Posts
    Use this:
    Code:
    function getSel() {
    	if (window.getSelection) {
    		return window.getSelection();
    	} else if (document.selection) {
    		return document.selection.createRange();
    	}
    }

  • #3
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts
    getSelection only returns plain text not HTML text. I need HTML text. That's my challenge.

  • #4
    Senior Coder
    Join Date
    Oct 2008
    Location
    Long Beach
    Posts
    1,196
    Thanks
    36
    Thanked 164 Times in 164 Posts
    This works in IE:
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Example</title>
    <style type="text/css">
    </style>
    <script type="text/javascript">
    // <![CDATA[
    
    function getSelectionHTML()
    	{
    	if (document.selection && document.selection.createRange) return (document.selection.createRange()).htmlText;
    	return null;
    	}
    
    function doSomething()
    	{
    	alert(getSelectionHTML());
    	}
    
    // ]]>
    </script>
    </head>
    <body>
    
    <div>blah blah <em>blah</em> blah <strong>blah</strong> blah</div>
    
    <input type="button" value="click me" onclick="doSomething()" />
    
    </body>
    </html>
    I'll brainstorm for a cross-browser version.
    Feel free to e-mail me if I forget to respond ;)
    ohsosexybrit@gmail.com

  • #5
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts
    There is no built-in methods for this on non-IE browsers. What has to be done is a a custom method of getting the start and end position of the getSelected text and then return the innerHTML in a substring. That should do it


    Thanks!

  • #6
    Senior Coder
    Join Date
    Oct 2008
    Location
    Long Beach
    Posts
    1,196
    Thanks
    36
    Thanked 164 Times in 164 Posts
    This doesn't work, but I need some sleep. Maybe you can arrive at a solution from some of the methods I used:
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Example</title>
    <style type="text/css">
    </style>
    <script type="text/javascript">
    // <![CDATA[
    
    function getSelectionHTML()
    	{
    	if (window.getSelection && (window.getSelection()).rangeCount == 1)
    		{
    		var selection_text = (window.getSelection()).toString();
    		var range = (window.getSelection()).getRangeAt(0);
    		var parent_html = range.commonAncestorContainer.innerHTML;
    		//var b = document.createElement("b");
    		//b.innerHTML = parent_html;
    		//var parent_text = b.innerText || b.textContent;
    		var first_text = range.startContainer.nodeValue.substr(range.startOffset);
    		var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);
    		var start = parent_html.indexOf(first_text);
    		var end = parent_html.indexOf(last_text,start+1)+last_text.length;
    		return parent_html.substring(start,end);
    		}
    	else if (document.selection && document.selection.createRange) return (document.selection.createRange()).htmlText;
    	return null;
    	}
    
    function doSomething()
    	{
    	alert(getSelectionHTML());
    	}
    
    // ]]>
    </script>
    </head>
    <body>
    
    <div>blah blah <em>blah</em> blah <strong>blah</strong> blah</div>
    
    <input type="button" value="click me" onclick="doSomething()" />
    
    </body>
    </html>
    Last edited by itsallkizza; 12-24-2008 at 08:01 AM.
    Feel free to e-mail me if I forget to respond ;)
    ohsosexybrit@gmail.com

  • Users who have thanked itsallkizza for this post:

    Joeweitzel (12-24-2008)

  • #7
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,277
    Thanks
    10
    Thanked 581 Times in 562 Posts
    look no further:

    Code:
    function selHTML() {
    
        if (window.ActiveXObject) {
            var c = document.selection.createRange();
            return c.htmlText;
        }
    
        var nNd = document.createElement("p");
        var w = getSelection().getRangeAt(0);
        w.surroundContents(nNd);
        return nNd.innerHTML;
    }
    Last edited by rnd me; 12-24-2008 at 08:12 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • The Following 2 Users Say Thank You to rnd me For This Useful Post:

    itsallkizza (12-24-2008), Joeweitzel (12-24-2008)

  • #8
    Senior Coder
    Join Date
    Oct 2008
    Location
    Long Beach
    Posts
    1,196
    Thanks
    36
    Thanked 164 Times in 164 Posts
    Range.surroundContents - didn't occur to me

    Nice job.

    Perhaps it may be slightly better to run object detection on the specific functions we're going to use though? Also if there is more than one range selected by the user, the code will only return the first range. Also changed "p" to "span" so it wouldn't interfere with the page layout.
    Code:
    function getSelectionHTML()
    	{
    	if (window.getSelection)
    		{
    		var sel = window.getSelection();
    		var html = "";
    		for (var i=0;i<sel.rangeCount;i++)
    			{
    			/*Author: rnd_me*/
    			var nNd = document.createElement("span");
    			var w = sel.getRangeAt(i);
    			w.surroundContents(nNd);
    			html += nNd.innerHTML;
    			}
    		return html;
    		}
    	else if (document.selection && document.selection.createRange) return (document.selection.createRange()).htmlText;
    	return null;
    	}
    This still adds a span every time you run it. Since the OP wanted to return the html of the selected text, it seems like it might be an issue adding html to the html in question... Maybe there's an easy way to remove the spans once we're done with them? .outerHTML = .innerHTML would do the trick if all browsers supported outerHTML (most do not ).
    Last edited by itsallkizza; 12-24-2008 at 01:53 PM.
    Feel free to e-mail me if I forget to respond ;)
    ohsosexybrit@gmail.com

  • #9
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Yes the surroundContents was the creativity I was looking for Thanks!

    I rewrote it to remove the added element, and now its working perfectly (you must pass the HTML text's parent element ):
    Code:
    function getSelectedHTML( element ) {
    	var sel = "";
    	if( window.getSelection ) {
    		sel = window.getSelection();
    	} else if ( document.getSelection ) {
    		sel = document.getSelection();
    	} else if ( document.selection && document.selection.createRange ) {
    		return ( element.selection.createRange() ).htmlText;
    	}
    	if( sel != "" ) {
    		var html = "";
    		for ( var i = 0; i < sel.rangeCount; i++ ) {
    			var nNd = document.createElement("span");
    			var w = sel.getRangeAt(i);
    			var prevInnerHTML = element.innerHTML;
    			w.surroundContents( nNd );
    			html += nNd.innerHTML;
    			element.innerHTML = prevInnerHTML;
    		}
    		return html;
    	}
    	return null;
    };
    One more issue:

    When you select HTML like this (underlined = selected text):

    This is some <strong>html text</strong> that has been selected.

    it returns "<strong>text</strong> that has been"
    when it should be returning "text</strong> that has been"

    Any ideas?
    Last edited by Joeweitzel; 12-24-2008 at 05:56 PM.

  • #10
    Senior Coder
    Join Date
    Oct 2008
    Location
    Long Beach
    Posts
    1,196
    Thanks
    36
    Thanked 164 Times in 164 Posts
    You don't need to pass anything:
    Code:
    function getSelectionHTML()
    	{
    	if (document.selection && document.selection.createRange) return (document.selection.createRange()).htmlText;
    	if (window.getSelection)
    		{
    		var sel = window.getSelection();
    		var html = "";
    		for (var i=0;i<sel.rangeCount;i++)
    			{
    			var d = document.createElement("span");
    			var r = sel.getRangeAt(i);
    			var parent_element = r.commonAncestorContainer;
    			var prev_html = parent_element.innerHTML;
    			r.surroundContents(d);
    			html += d.innerHTML;
    			parent_element.innerHTML = prev_html;
    			}
    		return html;
    		}
    	return null;
    	}
    Feel free to e-mail me if I forget to respond ;)
    ohsosexybrit@gmail.com

  • #11
    New Coder
    Join Date
    Dec 2008
    Posts
    21
    Thanks
    0
    Thanked 3 Times in 3 Posts
    I don't think you should put the content into a new <p> element using surroundsContents. You should just use extractContents.

  • #12
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Thanks, but that doesn't always work. Passing the element is more reliable

    What about the selection issue I mentioned. Any ideas? It seems to add the opening tag to the returned selected html when you select from before to after a close tag. Any ideas?

    Thanks!

  • #13
    Senior Coder
    Join Date
    Oct 2008
    Location
    Long Beach
    Posts
    1,196
    Thanks
    36
    Thanked 164 Times in 164 Posts
    Thanks, but that doesn't always work. Passing the element is more reliable
    When wouldn't it work? Having to pass an element greatly devalues this script's worth, so if there's holes in the code I'd like to fix them. There's definitely a way to do it without passing anything.


    What about the selection issue I mentioned. Any ideas?
    I think most people would want/expect it to function as it is currently functioning (ie including the opening tags). If you want to modify it for your personal needs, all you'd need to do is outcome.substr(outcome.indexOf(">")+1). That'll do exactly what you need.
    Last edited by itsallkizza; 12-24-2008 at 08:03 PM.
    Feel free to e-mail me if I forget to respond ;)
    ohsosexybrit@gmail.com

  • #14
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    6
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Sephr View Post
    I don't think you should put the content into a new <p> element using surroundsContents. You should just use extractContents.
    How did you want to use extraContents to do it?

    -Itsallkizza
    Thanks for the advise, I'll implement it all and post it once it's debugged..

  • #15
    New to the CF scene
    Join Date
    Apr 2009
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Code:
    var range = window.getSelection().getRangeAt(0);
    
    var startContainer = range.startContainer;
    var spanNode = startContainer.ownerDocument.createElement("layer");
    
    var docfrag = range.extractContents();
    spanNode.appendChild(docfrag);
    
    range.insertNode(spanNode);
    
    alert(spanNode.innerHTML);
    you can try this


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •