Search

Top Ten List

Of all my ramblings, people seem to find the following the most interesting:
  1. Pimp My Fields
  2. Using the WebBrowser control to view attachments inline
  3. Purty charts in Domino
  4. My approach to DbLookup and DbColumn in Javascript
  5. Mind Map of Database Design
  6. Design Catalog - version control for Domino
  7. Workaround for LotusScript event binding
  8. Clickable URL's in Notes view columns
  9. Every time you use window.open, God kills a kitten
  10. Create, edit, and delete without agents via AJAX

« 0.01 nanoseconds | Main| Dear lazyweb, what UPS should I buy? »

Every time you use window.open, God kills a kitten

Category javascript
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
What's a z-index? If you use layers in your Notes client development, you're already familiar with this concept: think of your user interface as existing in three-dimensional space. The x axis is horizontal, the y axis is vertical, and the z axis measures the conceptual distance between the "front" and the "back" of what's available to the user. Unlike x and y, however, which are typically measured in pixels or some other unit associated with the available width of the user's screen, the z index is theoretically limitless, and is simply identified by an integer. So on a web page (or a Notes layer), anything with a higher z-index is "closer" to the user; anything with a lower z-index is "further" away, and therefore displays "behind" the higher elements. Mozilla.org has a great tutorial on this concept if you want to dig deeper, but for the moment, just remember that the element with the highest z-index displays on top of everything else.

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

Gravatar Image1 - Well done. You've actually made me laugh out like a mad man twice today. My co-workers may soon committ me.
That's a very elequent way of providing popup functionality.

Gravatar Image2 - "Every time God closes a door, he opens a window"
Maria VonTrapp

Gravatar Image3 - ...so that's how all these moths are getting in...

Gravatar Image4 - It's 2008. Why can't we display code on the Internet with proper indenting? This is especially true in comments.

<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:-]

Gravatar Image5 - (pwned)

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 &nbsp;'s.

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Contact Me

Hire Me

Elsewhere

What the Quote?

"Hold me closer, Tony Danza."

Robert Rockey

"I'm pretty sure that the Great Leader is some sort of twisted ass freak."

Brent Bowers

"Voltron is just the K-Mart version of Transformers."

Laura Tripcony

"No, she's all four-cylinder ugly on the inside."

Laura Tripcony

"Put up your duchess."

Alex Belt

Apparel

Lotus Rocks

I write the code that makes the young girls cry

Current Terror Alert Level

Assorted Linkage

ClustrMap