Get Selected Text And Cursor Position With JavaScript To Show Popup Dialog
May 12, 2020 by Andreas Wik
Let’s look at how to grab the text the user has selected on the page as well as the cursor position, in order to show a little dialog underneath the text.
Every now and then I run into a site that has this little feature where when you select a piece of text in an article, a little dialog pops up, encouraging you to share the selected text on Facebook, X etc.
I thought it could be fun to build this.
The page
Before jumping into the JavaScript, let’s create a simple page with an article.
<article id="article">
<h1>
He Was a Crook
</h1>
<p>
Richard Nixon is gone now, and I am poorer for it. He was the real thing -- a political monster straight out of Grendel and a very dangerous enemy. He could shake your hand and stab you in the back at the same time. He lied to his friends and betrayed the trust of his family. Not even Gerald Ford, the unhappy ex-president who pardoned Nixon and kept him out of prison, was immune to the evil fallout. Ford, who believes strongly in Heaven and Hell, has told more than one of his celebrity golf partners that "I know I will go to hell, because I pardoned Richard Nixon."
</p>
</article>
Get selected text
First we need to decide when to look for selected text. I’ll go ahead and check on the mouseup event. This widget will be aimed at laptop/desktop users with a mouse. It doesn’t really make sense for touch device users as most iOS/Android/* browsers already show a dialog (with a Share option) when you select text.
const article = document.getElementById("article");
// On mouseup
article.addEventListener('mouseup', handlerFunction, false);
// Mouse up event handler function
function handlerFunction(event) {
// ... get selected text
}
Inside of our handlerFunction we’ll first check if there is any selected text by checking if what window.getSelection() returns isn’t empty by turning it into a string with toString() and checking the length. If something was selected, we can continue.
// Check if any text was selected
if(window.getSelection().toString().length > 0) {
}
I’m going to encode the selected text with encodeURIComponent(), and also escape certain characters as I don’t want exclamation marks and apostrophes etc to turn into like %21 when the user shares the text. As a fun test you can remove the replace() call and see what you get.
// Get selected text and encode it
const selection = encodeURIComponent(window.getSelection().toString()).replace(/[!'()*]/g, escape);
Get cursor position and create popup dialog
Alright, we got the selected text, now let’s create and insert a dialog.
I want to position the dialog just underneath the selected text. To do this, we can use X and Y position of the cursor. We get this from event.clientX and event.clientY.
I will tweak these values slightly to position it better. Play around with this to get the dialog positioned where you want. I will also get how much the user has scrolled and add that to the Y position value.
// Find out how much (if any) user has scrolled
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
// Get cursor position
const posX = event.clientX - 110;
const posY = event.clientY + 20 + scrollTop;
Now the last thing we need to do is create the dialog. I’ll add it to the end of the body with an absolute position, using the posX and posY I created above. I will also generate a X share URL so that if the user clicks “SHARE SELECTION” a share dialog shows up and they can share the text.
// Create X share URL
const shareUrl = 'http://x.com/share?text='+selection+'&url=https://awik.io';
// Append HTML to the body, create the "Share Selection" dialog
document.body.insertAdjacentHTML('beforeend', '<div id="share-snippet" style="position: absolute; top: '+posY+'px; left: '+posX+'px;"><div class="speech-bubble"><div class="share-inside"><a href="javascript:void(0);" onClick=\'window.open(\"'+shareUrl+'\", \"\", \"menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600\");\'>SHARE SELECTION</a></div></div></div>');
Complete final code:
const article = document.getElementById("article");
// We could also add the 'touchend' event for touch devices, but since
// most iOS/Android browsers already show a dialog when you select
// text (often with a Share option) we'll skip that
article.addEventListener('mouseup', handlerFunction, false);
// Mouse up event handler function
function handlerFunction(event) {
// If there is already a share dialog, remove it
if (document.contains(document.getElementById("share-snippet"))) {
document.getElementById("share-snippet").remove();
}
// Check if any text was selected
if(window.getSelection().toString().length > 0) {
// Get selected text and encode it
const selection = encodeURIComponent(window.getSelection().toString()).replace(/[!'()*]/g, escape);
// Find out how much (if any) user has scrolled
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
// Get cursor position
const posX = event.clientX - 110;
const posY = event.clientY + 20 + scrollTop;
// Create X share URL
const shareUrl = 'http://x.com/share?text='+selection+'&url=https://awik.io';
// Append HTML to the body, create the "Share Selection" dialog
document.body.insertAdjacentHTML('beforeend', '<div id="share-snippet" style="position: absolute; top: '+posY+'px; left: '+posX+'px;"><div class="speech-bubble"><div class="share-inside"><a href="javascript:void(0);" onClick=\'window.open(\"'+shareUrl+'\", \"\", \"menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600\");\'>SHARE SELECTION</a></div></div></div>');
}
}
Codepen Demo:
See the Pen Get selected text and position with JavaScript and show dialog by Andreas Wik (@andreaswik) on CodePen.
Take care and God bless!