JSFiddle - React, Tailwind, and code Playground
HTML
<p>Just select some text... This has worked across every browser that I have tested so far.</p>
<br />
<ol>
<li>Mac OSX FF15/FF16</li>
<li>Mac OSX Safari 5.1.7</li>
<li>Mac OSX Chrome 22</li>
<li>Mac OSX Opera 12</li>
<li>Win XP FF 3.6</li>
<li>Win XP Safari 3.1</li>
<li>Win XP IE7/IE8</li>
<li>Win 7 IE9</li>
<li>Win 7 FF15</li>
<li>Win 7 Chrome 22</li>
</ol>
<br />
<h2>Random Text to select...</h2>
<br />
<p>
<b>When you're a student or whatever, and you can't afford a car, or a plane fare, or even a train fare, all you can do is hope that someone will stop and pick you up.</b>
</p>
<p>
At the moment we can't afford to go to other planets. We don't have the ships to take us there. There may be other people out there (I don't have any opinions about Life Out There, I just don't know) but <b>it's nice to think that one could, even here and now, be whisked away just by hitchhiking.</b>
</p>
CSS
#__span__ {
display: inline !important;
*display: inline-block !important; /* IE7 works better with inline-block */
}
/* you can obviously ignore these, they are just used to show accuracy */
.crosshair-v {
height: 0;
width: 20px;
border-bottom: 1px solid red;
position: absolute;
margin-left: -10px;
}
.crosshair-h {
height: 20px;
width: 0;
border-right: 1px solid red;
position: absolute;
margin-top: -9px;
}
JavaScript
(function($){
$(function(){
var span = $('<span id="__span__" />').get(0),
crv = $('<div class="crosshair-v" />'),
crh = $('<div class="crosshair-h" />');
$('body').append(crv).append(crh);
var getSelectionTopLeft = function(){
var s,e,a,p,o,r,t;
try{
/// IE9, FF, Chrome, Safari, Opera
if ( window.getSelection ){
s = window.getSelection();
r = s.getRangeAt(0);
a = r.startContainer;
p = a.parentNode;
if ( a.nodeType == 3 ){
t = a.splitText(r.startOffset);
p.insertBefore(span, t);
}
else if ( a.nodeType == 1 ){
p.insertBefore(span, a);
}
o = $(span).position();
}
/// IE8-
else if ( (s = document.selection) && (s.type != 'Control') ) {
r = s.createRange();
r.move('character',0);
$('#__span__').remove();
r.pasteHTML(span.outerHTML);
o = $('#__span__').position();
}
/// quick fallback for certain older browsers
/// for whom $().position() fails.
if ( o && o.left === 0 && o.left === o.top ) {
e = span;
while( e.offsetParent ){
o.left += e.offsetLeft;
o.top += e.offsetTop;
e = e.offsetParent;
}
}
}catch(ex){}
return o;
}
$(document).mouseup(function(e){
/// execute our function to calculate the selection position
var o = getSelectionTopLeft();
if ( o ){
/// update the crosshair
crv.css(o);
crh.css(o);
}
});
});
})(typeof jQuery != 'undefined' && jQuery);