→ Facebox Sneak Peek

04 December 2007

I can feel it already: this blog is going to become the place where I sneak half-finished nuggets which don’t yet have their own place amongst the charmingly gratuitous rants we call Err.

Case in point: Facebox, my Facebook-inspired lightbox plugin. It uses jQuery and works with images, divs, and ajaxes. No IE testing yet, but that’s coming soon.

The secret demo page: http://famspam.com/facebox/

Here’s the full, pre-1.0 code. I’m only posting it to test out the Javascript highlighting on this blog:

/*
 * Facebox (for jQuery)
 * version: 1.0 (12/04/2007)
 * @requires jQuery v1.2 or later
 *
 * Examples at: http://famspam.com/facebox/
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007 Chris Wanstrath [ chris@ozmm.org ]
 *
 * Usage:
 *  
 *  jQuery(document).ready(function() {
 *    jQuery('a[@rel*=facebox]').facebox() 
 *  })
 *
 *  <a href="#terms" rel="facebox">Terms</a>
 *    Loads the #terms div in the box
 *
 *  <a href="terms.html" rel="facebox">Terms</a>
 *    Loads the terms.html page in the box
 *
 *  <a href="terms.png" rel="facebox">Terms</a>
 *    Loads the terms.png image in the box
 */

(function($) {
  $.fn.facebox = function(settings) {
    var settings = $.extend({
      loading_image : '/images/loading.gif',
      close_image   : '/images/closelabel.gif',
      image_types   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      facebox_html  : '\
  <div id="facebox" style="display:none;"> \
    <div class="popup"> \
      <table> \
        <tbody> \
          <tr> \
            <td class="tl"/><td class="b"/><td class="tr"/> \
          </tr> \
          <tr> \
            <td class="b"/> \
            <td class="body"> \
              <div class="content"> \
              </div> \
              <div class="footer"> \
                <a href="#" class="close"> \
                  <img src="" title="close" class="close_image" /> \
                </a> \
              </div> \
            </td> \
            <td class="b"/> \
          </tr> \
          <tr> \
            <td class="bl"/><td class="b"/><td class="br"/> \
          </tr> \
        </tbody> \
      </table> \
    </div> \
  </div>'
    }, settings)

    var image_types = settings.image_types.join('|')
    image_types = new RegExp('\.' + image_types + '$', 'i')

    function loading() {
      scroll()
      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+settings.loading_image+'"/></div>')
      $('#facebox').show()
    }

    function reveal(data) {
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
    }

    function scroll() {
      var offset = $('body').offset().top + 100
      $('html,body').animate({scrollTop: offset}, 500)
    }

    function show() {
      loading()

      var url    = window.location.href.split('#')[0]
      var target = this.href.replace(url,'')

      // support for rel="facebox[.inline_popup]" syntax, to add a class
      var klass = this.rel.match(/facebox\[\.(\w+)\]/)
      if (klass) {
        $('#facebox .content').addClass(klass[1])
      }

      // div
      if (target.match(/^#/)) {
        reveal($(target).clone().show())

      // image
      } else if (this.href.match(image_types)) {
        var image = new Image()
        image.onload = function() {
          reveal('<div class="image"><img src="' + image.src + '" /></div>')
        }
        image.src = target

      // ajax
      } else {
        $.get(target, function(data) { reveal(data) })
      }

      return false
    }

    function close() {
      $('#facebox').fadeOut(function() {
        $('#facebox .content').removeClass().addClass('content')
      })
      return false
    }

    function close_image() {
      $('#facebox .close_image').attr('src', settings.close_image)
    }

    ////
    // get real
    $('body').append(settings.facebox_html)

    var preload = [ new Image(), new Image() ]
    preload[0].src = settings.close_image
    preload[1].src = settings.loading_image
    
    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click(close)
    this.click(show)
    close_image()
  }
})(jQuery);