Go Back   CodingForums.com > :: Client side development > JavaScript programming

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 12-24-2008, 04:51 AM   PM User | #1
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
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
Joeweitzel is offline   Reply With Quote
Old 12-24-2008, 05:48 AM   PM User | #2
Sephr
New Coder

 
Join Date: Dec 2008
Posts: 21
Thanks: 0
Thanked 3 Times in 3 Posts
Sephr is an unknown quantity at this point
Use this:
Code:
function getSel() {
	if (window.getSelection) {
		return window.getSelection();
	} else if (document.selection) {
		return document.selection.createRange();
	}
}
Sephr is offline   Reply With Quote
Old 12-24-2008, 06:21 AM   PM User | #3
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
getSelection only returns plain text not HTML text. I need HTML text. That's my challenge.
Joeweitzel is offline   Reply With Quote
Old 12-24-2008, 06:57 AM   PM User | #4
itsallkizza
Senior Coder

 
Join Date: Oct 2008
Location: Long Beach
Posts: 1,196
Thanks: 36
Thanked 164 Times in 164 Posts
itsallkizza will become famous soon enough
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
itsallkizza is offline   Reply With Quote
Old 12-24-2008, 07:38 AM   PM User | #5
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
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!
Joeweitzel is offline   Reply With Quote
Old 12-24-2008, 07:52 AM   PM User | #6
itsallkizza
Senior Coder

 
Join Date: Oct 2008
Location: Long Beach
Posts: 1,196
Thanks: 36
Thanked 164 Times in 164 Posts
itsallkizza will become famous soon enough
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>
__________________
Feel free to e-mail me if I forget to respond ;)
ohsosexybrit@gmail.com

Last edited by itsallkizza; 12-24-2008 at 08:01 AM..
itsallkizza is offline   Reply With Quote
Users who have thanked itsallkizza for this post:
Joeweitzel (12-24-2008)
Old 12-24-2008, 08:09 AM   PM User | #7
rnd me
Senior Coder

 
rnd me's Avatar
 
Join Date: Jun 2007
Location: Urbana
Posts: 3,468
Thanks: 9
Thanked 466 Times in 450 Posts
rnd me is a jewel in the roughrnd me is a jewel in the roughrnd me is a jewel in the rough
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;
}
__________________
my site (updated 5/13)
STATS (2013/5) HTML5:90.2% MOB:14% IE7:0.5% IE8:8.6% IE9:9.8% IE10:10%

Last edited by rnd me; 12-24-2008 at 08:12 AM..
rnd me is offline   Reply With Quote
The Following 2 Users Say Thank You to rnd me For This Useful Post:
itsallkizza (12-24-2008), Joeweitzel (12-24-2008)
Old 12-24-2008, 01:40 PM   PM User | #8
itsallkizza
Senior Coder

 
Join Date: Oct 2008
Location: Long Beach
Posts: 1,196
Thanks: 36
Thanked 164 Times in 164 Posts
itsallkizza will become famous soon enough
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 ).
__________________
Feel free to e-mail me if I forget to respond ;)
ohsosexybrit@gmail.com

Last edited by itsallkizza; 12-24-2008 at 01:53 PM..
itsallkizza is offline   Reply With Quote
Old 12-24-2008, 05:25 PM   PM User | #9
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
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..
Joeweitzel is offline   Reply With Quote
Old 12-24-2008, 06:08 PM   PM User | #10
itsallkizza
Senior Coder

 
Join Date: Oct 2008
Location: Long Beach
Posts: 1,196
Thanks: 36
Thanked 164 Times in 164 Posts
itsallkizza will become famous soon enough
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
itsallkizza is offline   Reply With Quote
Old 12-24-2008, 07:10 PM   PM User | #11
Sephr
New Coder

 
Join Date: Dec 2008
Posts: 21
Thanks: 0
Thanked 3 Times in 3 Posts
Sephr is an unknown quantity at this point
I don't think you should put the content into a new <p> element using surroundsContents. You should just use extractContents.
Sephr is offline   Reply With Quote
Old 12-24-2008, 07:32 PM   PM User | #12
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
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!
Joeweitzel is offline   Reply With Quote
Old 12-24-2008, 08:01 PM   PM User | #13
itsallkizza
Senior Coder

 
Join Date: Oct 2008
Location: Long Beach
Posts: 1,196
Thanks: 36
Thanked 164 Times in 164 Posts
itsallkizza will become famous soon enough
Quote:
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.


Quote:
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.
__________________
Feel free to e-mail me if I forget to respond ;)
ohsosexybrit@gmail.com

Last edited by itsallkizza; 12-24-2008 at 08:03 PM..
itsallkizza is offline   Reply With Quote
Old 12-25-2008, 06:17 AM   PM User | #14
Joeweitzel
New to the CF scene

 
Join Date: Dec 2008
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Joeweitzel is an unknown quantity at this point
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..
Joeweitzel is offline   Reply With Quote
Old 04-17-2009, 06:20 PM   PM User | #15
neverwinter
New to the CF scene

 
Join Date: Apr 2009
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
neverwinter is an unknown quantity at this point
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
neverwinter is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 04:29 PM.


Advertisement
Log in to turn off these ads.