I am working on a chrome extension where I need to display a pop-up on the selection of text on any website just like the image attached below.(Similar example is implemented here).
Though I am able to read the content and position, I am not displaying pop-up at the right position. Any help would be appreciated.
Here is the snippet :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Custom menu on text selection</title>
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<style>
.menu {
display: none;
position: absolute;
background: #a4a4a4;
border-radius: 6px;
}
</style>
<script>
var pageX, pageY;
document.addEventListener("mouseup", () => {
if (document.querySelector(".menu") != null) {
document.querySelector(".menu").remove();
}
let selection = document.getSelection();
let selectedText = selection.toString();
//this div will diplay in popup
var iDiv = document.createElement("div");
iDiv.className = "menu";
iDiv.innerHTML = '<i class="fa fa-copy fa-2x" id="copy-btn"></i>';
document.body.appendChild(iDiv);
var menu = document.querySelector(".menu");
//if the text is not empty show dialog
if (selectedText !== "") {
var range = window.getSelection().getRangeAt(0);
let rect = range.getBoundingClientRect();
menu.style.display = "block";
var left = Math.round(rect.left) + "px";
var top = Math.round(rect.top) + "px";
} else {
//if the text is empty hide existing dialog
menu.style.display = "none";
}
});
document.addEventListener("mousedown", (e) => {
pageX = e.pageX;
pageY = e.pageY;
});
</script>
</head>
<body>
<div>
<p>
In today’s digital world, when there are thousands of online platforms (maybe more than that!) available over the web, it becomes quite difficult for students to opt for a quality, relevant and reliable platform for
themselves. Meanwhile, as Computer Science is a very vast field hence students are required to find an appropriate platform that can fulfill all their needs such as – Tutorials & Courses, Placement Preparation, Interview
Experiences, and various others. And with the same concern, GeeksforGeeks comes in the picture – a one-stop destination for all Computer Science students!!
</p>
</div>
</body>
</html>
This is the expected output:
You can use event
clientX
and clientY
to get the position os selected text and show dynamic pop up there. Example code is attached below. For more refer to andreaswik blog post.
In html:
<div>
<p>
In today’s digital world, when there are thousands of online platforms
(maybe more than that!) available over the web, it becomes quite
difficult for students to opt for a quality, relevant and reliable
platform for themselves. Meanwhile, as Computer Science is a very vast
field hence students are required to find an appropriate platform that
can fulfill all their needs such as – Tutorials & Courses, Placement
Preparation, Interview Experiences, and various others. And with the
same concern, GeeksforGeeks comes in the picture – a one-stop
destination for all Computer Science students!!
</p>
</div>
<div>
In CSS file
.speech-bubble {
position: relative;
background: #4294da;
border-radius: .4em;
color: white;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 0;
left: 50%;
width: 0;
height: 0;
border: 12px solid transparent;
border-bottom-color: #4294da;
border-top: 0;
margin-left: -12px;
margin-top: -12px;
}
.share-inside {
background: url('https://awik.io/demo/js-selected-text/twicon.png');
background-repeat: no-repeat;
background-position: 10px center;
background-size: 24px 19px;
}
.share-inside a {
display: inline-block;
text-decoration: none;
color: #ffffff;
font-size: 14px;
padding: 10px;
padding-left: 40px;
}
In js
document.addEventListener('mouseup', handlerFunction, false);
// Mouse up event handler function
function handlerFunction(event) {
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 Twitter share URL
const shareUrl = 'http://twitter.com/share?text='+selection+'&url=https://awik.io';
// Append HTML to the body, create the "Tweet 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\");\'>TWEET SELECTION</a></div></div></div>');
}
}