Tuesday, November 04, 2008

FancyBox, jQuery and z-index

So yesterday I'm working with the jQuery plugin called FancyBox. It's a great little popup gizmo, similar to Lightbox, Thickbox, et. al. But I'm having a problem. In the page I'm working in, I find that we have some crazy high z-index values having been set. One of them is 100,000. Dude. Crazy.

Anyway...so I wrote a small jQuery-based javascript to determine the highest z-index value of all the elements within the page. After some research into the jQuery selectors, I find what I need. Unfortunately, as I return the .css("zIndex") value back from each object, compare it to a running max, I find that in the end the value "auto" is the highest. That's not helpful. I end up finding a simple isNumeric() function I can include, but it only checks the characters in the value against numbers and the decimal point. So I find that, with my routine, 2000 > 100000. Um...that's not right. That lets me know, though, that it's not comparing numbers to numbers, but rather numbers and character values. The parseInt() function solves this.

In the end, here's the basic function I came up with, how to determine the greatest z-index on the page, using jQuery:
<script>
  var zmax = 0 ;
  function buildZMax() {
    $('*').each(function() {
      var cur = parseInt($(this).css('zIndex'));
      zmax = cur > zmax ? $(this).css('zIndex') : zmax;
    });
  }
</script>

With this, you can now call buildZMax() and the var zmax will hold the highest value. Now, that's not all I set out to do. Getting the highest z-index value was the prelude to modifying my FancyBox setups to make sure the FancyBox is on top of everything.

Here's how it ended up looking, though we will modify more today to actually incorporate this functionality directly into the FancyBox code, submit it to the author, and perhaps he'll include it in his next version. But this will get you by:

 <script>
   var zmax = 0 ;
   
   function buildZMax() {
     $('*').each(function() {
       var cur = parseInt($(this).css('zIndex'));
       zmax = cur > zmax ? $(this).css('zIndex') : zmax;
     });
   }

   function goFancy() {
     buildZMax();

     // Get all the outermost fancy_wrap id'ed objects built by the FancyBox calls
     // ...then bump the z-index to whatever the highest we found, plus 1
     $('#fancy_wrap').each(function() {
       zmax = zmax + 1 ;
       $(this).css("z-index", zmax);

       // Get the overlay children in each iteration of the outer
       // ...fancy_wrap, bump it's z-index up.
       $(this).children("div#fancy_overlay").each(function() {
         zmax = zmax + 1 ;
         $(this).css("z-index", zmax);
       });

       // And again for another major child div
       zmax = zmax + 1 ;
       $(this).children("div#fancy_outer").each(function() {
         zmax = zmax + 1 ;
         $(this).css("z-index", zmax);
       });
     });
 });

   $(document).ready(function(){
     $("a#myFancyLink").fancybox({
       'frameWidth': 600,
       'frameHeight': 600,
       'overlayShow': true
     });

     // Call our z-index fixer.
     goFancy() ;

   });
  </script>

Now, something a bit important to note here. You very likely, if you're a jQuery user, have other scripts that might be creating objects, etc. as you go along. It might be beneficial to put your goFancy() call near the end of your document.ready() code to ensure this ends up where you need it. But the buildZMax() function might very well come in handy for other things you might develop with.

Also, while the selectors in jQuery are screaming fast, if you know that you never, ever put z-index on anything but, say, <div> tags, then replace the "*" in the line:
$('*').each(function() {
... with "div" or whatever you apply your z-index'es to. This will make the whole function run faster, obviously.

Post a comment if you're interested in our incorporation to Fancybox code directly.

- Will Belden
Tuesday, November 4, 2008

4 comments:

bittercoder said...

I just hit this issue myself, thanks for saving me a few minutes of head scratching :)

Did the original author ever end up adding this functionality directly into his plugin?

Will Belden said...

@bittercoder: If they did, they never got back with me after my email. I'm not sure that me email was ever replied to. I can't find it in my Gmail, so no telling.

Jacob said...

this works as long as the content your loading in the fancybox does not use zindex otherwise the fancybox loads 'above' the content making this script pointless..

Will Belden said...

@Jacob: Do you have any alternatives or suggestions?