My use-case is this: I have a list of files that users can click on to download. I’d like them to be able to hover over a file and see the file size and checksum. I also want them to be able to select and copy the checksum value to their clipboard if so desired. Initializing the popover on each item and manually getting it to show on mouseover works fine. However, I’m not sure how to hide the popover. I was hoping I could add a mouseleave eventListener to the popover itself, but that doesn’t seem to be an option. Obviously, I want to reserve clicking of the element itself for initiating the download.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.0/css/all.min.css" integrity="sha512-9xKTRVabjVeZmc+GUW8GgSmcREDunMM+Dt/GrzchfN8tkwHizc5RP4Ok/MXFFy5rIjJjzhndFScTceq5e6GvVQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>
</head>
<body>
<br/>
<a href="#"
data-bs-toggle="popover"
data-bs-content="size: 5MB<br/>sha1: 123456789"
>
FILE_TO_DOWNLOAD_1
</a>
<br/>
<br/>
<a href="#"
data-bs-toggle="popover"
data-bs-content="size: 5MB<br/>sha1: 123456789"
>
FILE_TO_DOWNLOAD_2
</a>
<script>
$(document).ready(function() {
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
var popoverList = popoverTriggerList.map(function(popoverTriggerEl) {
var popover = new bootstrap.Popover(popoverTriggerEl, {
container: 'body',
html: true,
trigger: 'manual'
});
popoverTriggerEl.addEventListener('mouseover', (event) => {
popover.show();
});
return popover;
});
});
</script>
</body>
2
Answers
Idea is to allow for a few ms delay before hiding the popover. This grace period is cancel the hiding should the element or the popover got hovered.
Technically, each popover’s
tip
property gives a handle to the popover element, so you canaddEventListener
to it.For a nicer touch, we close all other popovers when opening a new one.
I implemented the following solution:
Just like you, I use a mouseover event to show the popover. However, I also store a reference to the element to avoid repeating the event.
After that, I add a class to the element to identify it using jQuery’s is function (equivalent to matches in vanilla JavaScript).
Finally, I add an event to the element that monitors all mouseover and mouseout events. If any of these events indicate that the mouse is no longer over the clicked button or the popover itself, I close the popover.
I added debounce because when you move the mouse between the clicked element and the popover, there’s a small gap between them. Without debounce, which adds a slight delay, the hide event would trigger immediately.
In simpler and more summarized terms: When you click the button, the popover is activated and only disappears from the screen when the user moves the mouse away from both elements.