I needed to write a quick bit of code today to track when a user selects any text on a page. The key was to bind a method to the "mouseup" event which would grab the selected text and do something with it. This was plain 'ole JS and thankfully <a href="http://dean.edwards.name">Dean Edwards</a> and <a href="http://crisp.tweakblogs.net/">Tino Zijdel</a> had created a nice <a href="http://therealcrisp.xs4all.nl/upload/addEvent_dean.html">cross-browser event handler routine</a> which worked great. And <a href="http://davidwalsh.name/">David Walsh</a> has a <a href="http://davidwalsh.name/text-selection-ajax">nice post on similar functionality</a> using MooTools & jQuery so I was able to leverage some of that code that deals with grabbing the selected text:

[code lang="js"]
function findSelected() {
	if(window.getSelection) { 
		return window.getSelection(); 
	}
	else if(document.getSelection) { 
		return document.getSelection(); }
	else {
		var selection = document.selection &amp;&amp; document.selection.createRange();
		if(selection.text) { 
			return selection.text; }
		return false;
	}
	return false;
}

function getSelectedText() {
	var selected = findSelected();
	if(selected &amp;&amp; (selected = new String(selected).replace(/^\s+|\s+$/g,''))) {
		alert( selected );
	}
}
[/code]

From there it was just a matter of actually binding the method to "mouseup":

[code lang="js"]
addEvent(document,&quot;mouseup&quot;,getSelectedText);
[/code]

All this seemed great and it worked perfectly in Internet Explorer and Firefox but when I tried it on Chrome, I found an issue. When I would select the whole line of text an alert box would appear which was expected but when I closed the box and clicked on any whitespace in the viewport, the alert box would reappear! To see it in action, try these steps:

<ol>
	<li>Open this page: <a href="http://reybango.com/ms/test.html">http://reybango.com/ms/test.html</a></li>
	<li>Using your mouse select the whole line of the text and release. An alert box should appear.</li>
	<li>Close the alert box and click on any whitespace in the viewport.</li>
</ol>

In both Chrome and Safari, you should see that a second alert box is displayed containing the selected text. This doesn't happen in Firefox or IE. It also won't happen if you only select part of the text. It has to be the <strong>whole</strong> line.

After quite a bit of debugging, running it by John Resig & Pete Higgins and running short on time, I decided to create a work-around which resolved the issue. By using a closure to keep a persistent copy of the last selected text, I can compare that value to the newly selected text and if it matches the persistent copy, I can ignore it. It's a very basic way to filter out the second call being done by Chrome & Safari:

[code lang="js"]
getSelectedText = (function() {
	var selected = &quot;&quot;;
	
	return (function() {
		var currSelection = findSelected();
		if (selected != currSelection) {
			selected = currSelection;
			if(selected &amp;&amp; (selected = new String(selected).replace(/^\s+|\s+$/g,''))) {
				alert( selected );
			}
		}
	})
})();
[/code]

Here's the working <a href="http://reybango.com/ms/test-closure.html">demo</a>.

Now I acknowledge that this is not the ideal solution and I need to determine what the browser inconsistency is here. It seems like it might be Webkit-related since it only affects Chrome & Safari so I'll have to dig further into that. For now, though, the closure works and since I don't a circular reference between any DOM or JS objects, it looks like memory leaks shouldn't be an issue. 