Every time you use window.open, God kills a kitten
I was booking some travel recently and couldn't select a date on one of the travel sites because they were using window.open, so my browser blocked it as a popup. They weren't trying to sell me anything I wasn't planning on buying anyway, they weren't trying to install malware, it was just a date picker. But I couldn't use it without modifying my browser's security settings (or switching to a less secure browser). It's 2008... window.open? Seriously?So, for any of you who still use window.open to display a date picker, or a comment form (see Andrew's blog as an example of the right way to do this), or... well, anything else... and the only reason is because you asked someone for an alternative and were simply told, "duh, use a positioned div" - but not told how - hopefully this post will show you how easy a better alternative can be.
To display something that looks like a popup but really isn't, all you really need is:
- a div that hides until needed and has a higher z-index than the rest of the page
- code to show and hide that div, and position it where you want it to display
Here is an example (also available for download) of using a "positioned div" to display additional content that you might otherwise launch in a separate window with window.open. To enable this, start out by creating a div somewhere in your page markup, give it an id and a class (in my example, I'm using "pseudoWindow" as the id and "layerwindow" as the class), and define some CSS for that class:
div.layerwindow {
background-color: #eeeeee;
border: 3px solid #abcdef;
display: none;
overflow: scroll;
padding: 3px;
position: absolute;
z-index: 2;
}
This causes that div to hide initially, as well as defining how it will look when it's no longer hidden.
Next, you'll need some JavaScript code for showing the div, positioning it, and hiding it again:
var LayerWindow = function(){
var getViewPort = function(){
var viewPortWidth;
var viewPortHeight;
var vYscroll;
if (window.innerWidth) {
viewPortWidth = window.innerWidth;
viewPortHeight = window.innerHeight;
vYscroll = window.pageYOffset;
} else if (document.documentElement && document.documentElement.clientWidth) {
viewPortWidth = document.documentElement.clientWidth;
viewPortHeight = document.documentElement.clientHeight;
vYscroll = document.documentElement.scrollTop;
} else {
var bodyTag = document.getElementsByTagName('body')[0];
viewPortWidth = bodyTag.clientWidth;
viewPortHeight = bodyTag.clientHeight;
vYscroll = document.body.scrollTop;
}
return {
w: viewPortWidth,
h: viewPortHeight,
yScroll: vYscroll
};
};
return {
open: function(id, options){
var vp = getViewPort();
if (document.getElementById(id)) {
overlayer = document.getElementById(id);
overlayer.style.width = options.w + 'px';
overlayer.style.height = options.h + 'px';
overlayer.style.top = (vp.yScroll + parseInt(vp.h / 2, 10) - parseInt(options.h / 2, 10)) + 'px';
overlayer.style.left = (parseInt(vp.w / 2, 10) - parseInt(options.w / 2, 10)) + 'px';
overlayer.style.display = 'block';
}
return false;
},
close: function(id){
document.getElementById(id).style.display = 'none';
}
};
}();
Finally, update whatever would be triggering the window.open to instead just display the hidden div:
<a href="#" onclick="return LayerWindow.open('pseudoWindow', {'w':300, 'h':250});">Open layer window</a>
There are a multitude of ways to add further elegance and functionality to this (and nearly every widely used JavaScript framework has their own implementation) - for example, loading the content of the hidden div via AJAX prior to displaying it instead of using pre-populated content - but hopefully this will give you a head start toward eliminating your own use (if any) of window.open... please, think of the kittens.
(cross-posted at BleedYellow)








Comments
That's a very elequent way of providing popup functionality.
Posted by Nick Malone At 18:16:00 On 07/02/2008 | - Website - |
Maria VonTrapp
Posted by pops At 13:53:49 On 07/03/2008 | - Website - |
Posted by Tim Tripcony At 15:38:03 On 07/03/2008 | - Website - |
<code>
main{
printf("Hello, its 2008!";
}
</code>
Man, that annoying ... and hard to read. I'd take formatting over graphical emoticons any day.
Otherwise, great article.
Peace,
Rob:-]
Posted by Rob At 17:10:32 On 07/03/2008 | - Website - |
Touché, Rob. The code-to-html tool I've been using doesn't preserve indenting, so I've updated this post to add all the necessary 's.
Posted by Tim Tripcony At 17:41:21 On 07/03/2008 | - Website - |