Creating Hover-Based Pop-Up Info Windows
Problem
You like the Netflix website’s pop-up window that displays when the mouse cursor is over a movie thumbnail, and you want to incorporate this functionality into your own application.
Solution
The Netflix-style of pop-up info window is based on four different functionalities.
First, you need to capture the mouseover and mouseout events for each image thumbnail,
in order to display or remove the pop-up window, respectively. In the following code,
the cross-browser event handlers are attached to all images in the page:
window.onload=function() { var imgs = document.getElementsByTagName("img"); for (var i = 0; i < imgs.length; i++) { imgs[i].addEventListener("mouseover",getInfo, false); imgs[i].addEventListener("mouseout",removeWindow, false); } }
Second, you need to access something about the item you’re hovering over in order to know what to use to populate the pop-up bubble. The information can be in the page, or you can use web server communication to get the information:
function getInfo() { // prepare request if (!xmlhttp) { xmlhttp = new XMLHttpRequest(); } var value = this.getAttribute("id"); var url = "photos.php?photo=" + value; xmlhttp.open('GET', url, true); xmlhttp.onreadystatechange = showWindow; xmlhttp.send(null); return false; }
Third, you need to either show the pop-up window, if it already exists and is not dis‐ played, or create the window. In the following code, the pop-up window is created just below the object, and just to the right when the web server call returns with the infor‐ mation about the item.
The getBoundingClientRect() method is used to determine the location where the pop up should be placed, and createElement() and create TextNode() are used to create the pop up:
// compute position for pop up function compPos(obj) { var rect = obj.getBoundingClientRect(); var height; if (rect.height) { height = rect.height; } else { height = rect.bottom - rect.top; } var top = rect.top + height + 10; return [rect.left, top]; } // process return function showWindow() { if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { var response = xmlhttp.responseText.split("#"); var img = document.getElementById(response[0]); if (!img) return; // derive location for pop up var loc = compPos(img); var left = loc[0] + "px"; var top = loc[1] + "px"; // create pop up var div = document.createElement("popup"); div.id = "popup"; var txt = document.createTextNode(response[1]); div.appendChild(txt); // style pop up div.setAttribute("class","popup"); div.setAttribute("style","left: " + left + "; top: " + top); document.body.appendChild(div); } }
Lastly, when the mouseover event fires, you need to either hide the pop-up window or remove it—whichever makes sense in your setup. Since the application created a new pop-up window in the mouseover event, it removes the pop-up in the mouseout event handler:
function removeWindow() { var popup = document.getElementById("popup"); if (popup) popup.parentNode.removeChild(popup); return false; }
EXPLAIN
Creating a pop-up information or help window doesn’t have to be complicated if you
keep the action simple and follow the four steps outlined in the solution. If the pop up
provides help for form elements, then you might want to cache the information within
the page, and just show and hide pop-up elements as needed.
However, if you have pages
like the ones at Netflix, which can have hundreds of items, you’ll have better perfor‐
mance if you get the pop-up window information on demand via a web service call (i.e.,
Ajax or WebSockets). The solution demonstrates that using web calls doesn’t add sig‐
nificant additional complexity to the application.
When I positioned the pop up in the example, I didn’t place it directly over the object.
The reason is that I’m not capturing the mouse position to have the pop up follow the
cursor around, ensuring that I don’t move the cursor directly over the pop up. But if I
statically position the pop up partially over the object, the web page readers could move
their mouse over the pop up, which triggers the event to hide the pop up…which then
triggers the event to show the pop up, and so on.
This creates a flicker effect, not to
mention a lot of network activity.
If, instead, I allowed the mouse events to continue by returning true from either event
handler function, when the web page readers move their mouse over the pop up, the
pop up won’t go away.
However, if they move the mouse from the image to the pop up,
and then to the rest of the page, the event to trigger the pop-up event removal won’t fire,
and the pop up is left on the page.
The best approach is to place the pop up directly under (or to the side, or a specific
location in the page) rather than directly over the object. This is the approach Netflix
uses on its site.
No comments:
Post a Comment