For a project I needed a snippet which presents arbitrary HTML code in a tooltip like popup window, when the mouse hovers over an HTML ELement. I couldn't find one solving my complete problem, but on https://www.w3schools.com/howto/howto_js_popup.asp I found a suitable template to build on.
<!DOCTYPE html>
<html>
<head>
<style>
/* copied and slightly modified from w3schools */
.popup_host_class {
position: relative;
}
.popup_host_class .popup {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
.popup_host_class .popup::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.popup_host_class .show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
.popup_host_class .triggered {
border-radius: 6px;
border-width: 1px;
border-color: #000;
border-style: solid;
}
/* Add animation (fade in the popup) */
@-webkit-keyframes fadeIn {
from {opacity: 0;}
to {opacity: 1;}
}
@keyframes fadeIn {
from {opacity: 0;}
to {opacity:1 ;}
}
</style>
<body>
<div id="popup_host" class="popup_host_class">Hover over me!</div>
<script>
const ENTER_DELAY=1000;
const POPUP_DELAY=1000;
function popup_element() {
var node = document.createElement("span");
node.setAttribute("id","PopupElement");
node.innerHTML="Popuptext";
return node;
}
var popup_host = document.getElementById("popup_host");
popup_host.addEventListener("mouseenter", function (event) {
this.classList.add("triggered");
/*
* After the mouse has entered the host, we wait for
* ENTER_DELAY ms before we who the popup
*/
this.mouseover_timeout_fn = setTimeout( function(arg) {
arg[0].classList.remove("triggered");
let popup = popup_element();
popup.classList.add("popup");
popup.classList.add("show");
/*
* We close the popup after we click on it...
*/
popup.addEventListener("click", function () {
if (this.fade_out_timer) {
clearTimeout(this.fade_out_timer);
his.fade_out_timer = null;
}
this.classList.remove("show");
});
/*
* ...or after POPUP_DELAY has passed, unless...
*/
popup.addEventListener("mouseout", function () {
if (this.classList.contains("show")) {
this.fade_out_timer = setTimeout ( function (iarg) {
iarg[0].fade_out_timer = null;
iarg[0].classList.remove("show");
}, POPUP_DELAY, [this]);
}
});
/*
* ... the mouse is on the popup.
*/
popup.addEventListener("mouseenter", function () {
if (this.fade_out_timer) {
clearTimeout(this.fade_out_timer);
this.fade_out_timer = null;
}
});
/*
* we start the initial POPUP_DELAY
*/
popup.fade_out_timer = setTimeout ( function (iarg) {
iarg[0].fade_out_timer = null;
iarg[0].classList.remove("show");
}, POPUP_DELAY, [popup]);
/*
* and add the popup to its host
*/
arg[0].append(popup);
}, ENTER_DELAY, [this] );
});
/*
* After the mouse has left the host without
* ENTER_DELAY having passed, we cancel the popup display
*/
popup_host.addEventListener("mouseout", function (event) {
if ( this.mouseover_timeout_fn ) {
this.classList.remove("triggered");
clearTimeout(this.mouseover_timeout_fn);
this.mouseover_timeout_fn = null;
}
});
</script>
</body>
</html>