/**
 * jQuery plugins used by Atom
 *
 * @link http://ellishmarketing.com
 *
 * @package ATOM
 * @subpackage Template
 */



// simple tabbed interface
// @todo add option to load section content trough ajax (for theme settings)
(function($){
  $.fn.tabs = function(){
    return this.each(function(){

      // -- markup should follow this pattern:
      //
      //   <div class="tabs" id="my-tab-instance">
      //     <ul class="navi">
      //        <li class="active"><a href="#tab-first">first</a></li>
      //        <li><a href="#tab-second"second/a></li>
      //     </ul>
      //     <div class="section" id="tab-first">
      //        first
      //     </div>
      //     <div class="section" id="tab-second">
      //        second
      //     </div>
      //   </div>

      var tabs = $(this),
          instance = tabs.attr('id');

      $('.section', tabs).css({'position' : 'absolute', 'width': '100%'});
      $('.sections', tabs).css('height', $('#' + $('.navi li.active a', tabs).attr('href'), tabs).outerHeight(true));

      $('.navi li a', tabs).bind(tabs.data('event') || 'click', function(event){

        // only proceed if the current item is not selected and if there are no animations with the current block or block <li>'s
        if($('.sections, .sections li', tabs).is(':animated') || $(this).parent('li').hasClass('active')) return false;

        event.preventDefault();
        var current = $('#' + $('.navi li.active', tabs).removeClass('active').find('a').attr('href'), tabs),
            next = $('#' + $(this).parent('li').addClass('active').find('a').attr('href'), tabs);

        $.cookie(instance , next.attr('id'), { path: '/' });

        switch(tabs.data('fx')){
          case 'height':
            $('.sections', tabs).animate({ 'height': 0 }, { duration: 333, easing: 'easeInBack', complete: function(){
              current.hide();
              next.show();
              $(this).animate({ 'height': next.outerHeight(true) }, { duration: 333, easing: 'easeOutCirc'});
            }});

          break;
          case 'fade':
            current.fadeOut(333);
            next.fadeIn(333);
            $('.sections', tabs).animate({ 'height': next.outerHeight(true) }, {
               duration: 300,
               specialEasing: { opacity: 'easeOutQuad',  height: 'easeOutExpo' }
            });
          break;
          default:
            current.hide();
            next.show();
            $('.sections', tabs).css('height', next.outerHeight(true));
          break;
        }

      });

      // override if tab is present in hash (URL)
      $('.navi li a', tabs).each(function(){
        if(window.location.hash == $(this).attr('href')) $(this).trigger('click');
      });

    });
  }
})(jQuery);



// 960gs overlay -- used in theme preview mode only
(function($){
  $.fn.gridOverlay = function(cfg){
    cfg = $.extend({
      columns: 12,
      columnWidth: 60,
      color: '#ccc',
      opacity: 40
    }, cfg);

    var frame = $('<div style="display:none;overflow:hidden;position:absolute;left:0;top:0;width:100%;height:'+(this.height()-40)+'px;z-index: 999;">'),
        grid = $('<div style="position:relative;width:960px;height:100%;margin:0 auto;overflow:hidden;">'),
        trigger = $('<a style="position:fixed;top:140px;left:20px;cursor:pointer;padding:5px;background:red;color:#fff;font-weight:bold;z-index:9999;">GRID</a>');

    trigger.appendTo('#page').click(function(){
      frame.toggle();
    });

    for(var i = 0; i < cfg.columns; i++){ // columns
      grid.append('<div style="width:'+((i != 0) ? 20 : 10)+'px;float:left;height:100%;"></div>');
      grid.append('<div style="width:'+cfg.columnWidth+'px;height:100%;float:left;background:'+cfg.color+';opacity:'+(cfg.opacity/100)+';"></div>');
    }

    return this.each(function(){
      $(this).prepend(frame.prepend(grid));
    });

  };
})(jQuery);



// used to highlight search queries
(function($){
  $.fn.highlightText = function(text, insensitive, highlightClass){
    var regex = new RegExp('(<[^>]*>)|(\\b' + text.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1') + ')', insensitive ? 'ig' : 'g');

    if(this.length > 0) return this.html(this.html().replace(regex, function(a, b, c){
      return (a.charAt(0) == '<') ? a : '<strong class="' + highlightClass + '">' + c + '</strong>';
    }));

  };
})(jQuery);



// expand-collapse list - slightly based on jQuery Menu by Marco van Hylckama Vlieg - http://www.i-marco.nl/weblog/
// @todo finish accordion style menu
(function($){
  $.fn.CollapsibleMenu = function(){

    return this.each(function(){

      $('li.extends', this).addClass('collapsed');
      $('li.extends.active, li.extends.active-parent', this).removeClass('collapsed').addClass('expanded');

      var classes = $(this).attr('class'),
          event = /event-([^\s]+)/.exec(classes)[1];

      $('li.extends span.expand, li.extends a[href="#"]', this).bind(event, function(event){
        event.stopImmediatePropagation();

        var trigger = $(this),
            theElement = trigger.nextAll('ul:first'),
            parent = trigger.parent(),
            menu = trigger.closest('.collapsible, .accordion'),
            slide = function(e, fx){
              $(e).animate({ // slide[Direction] equivalent -- we use this instead of slideDown/slideUp/slideToggle for the step property (to fix the tab height glitch)
                'opacity': fx,
                'height': fx,
                'marginTop': fx,
                'marginBottom': fx,
                'paddingTop': fx,
                'paddingBottom': fx
              },
              { duration: 200,
                step: function(now, fx){ menu.parents('li.block .sections').height(menu.height()); },
                complete: function(){
                  parent.removeClass('expanded collapsed');
                  if(theElement.is('ul:visible')) parent.addClass('expanded'); else parent.addClass('collapsed');
                }
              });
            };

        if(menu.hasClass('collapsible')){
          if(theElement[0] === undefined) window.location.href = this.href;
          slide(theElement, 'toggle');
          return false;
        }else{
          context_menu = this.parentNode.parentNode;
          if(theElement.is('ul:visible')){
            if(menu.hasClass('collapsible')){
              slide($('ul:visible', context_menu).first(), 'hide'); // slide up
              return false;
            }
            return false;
          };
          if(!theElement.is('ul:visible')){
            slide($('ul:visible', context_menu).first(), 'hide'); // slide up
            slide(theElement, 'show'); // slide down
            return false;
          }
        }

        return false;
      });

    });
  };
})(jQuery);



// create a single tooltip with the current element's title, and append it to the body (to avoid overflow issues)
(function($){
  $.fn.bubble = function(){
    var tip = $('<div class="tip"></div>').appendTo('body'),
        title;

    return this.mouseover(function(){
      title = $(this).attr('title');
      tip.html(title);
      $(this).attr('title', '');
      tip.show();
    }).mousemove(function(e){
      tip.css({
        top: e.pageY + 22,
        left: e.pageX + 10
      });
    }).mouseout(function(){
      tip.hide();
      $(this).attr('title', title);
    }).click(function(){
      tip.hide();
      $(this).attr('title', title);
    });

  };
})(jQuery);



// form input field helpers
// based on clearField 1.1 by Stijn Van Minnebruggen - http://www.donotfold.be
(function($){
  $.fn.clearField = function(cfg){

    cfg = $.extend({
      blurClass: 'clearFieldBlurred',
      activeClass: 'clearFieldActive',
      attribute: 'data-default',
      value: ''
    }, cfg);

    return this.each(function(){

      var field = $(this),
          placeholder = field.attr(cfg.attribute),
          has_pwd_label = false;

      // @todo: use the <placeholder> tag if the browser supports it;
      // currently very few browsers are able to style it, so we're sticking to clearField...
      //var placeholderSupported = !!('placeholder' in document.createElement($(this).get(0).tagName));

      cfg.value = field.val();

      if(placeholder == undefined)
        field.attr(cfg.attribute, field.val()).addClass(cfg.blurClass);
      else
        cfg.value = placeholder;

      if(field.is(':password')){
        var pwd_label = $('<input type="text" />').attr('class', field.attr('class')).val(placeholder).addClass('pass-label').hide();
        field.after(pwd_label);
        has_pwd_label = true;
        pwd_label.focus(function(){
          pwd_label.hide();
          field.show().focus();
        });

      }

      field.focus(function(){

        if(field.val() == placeholder && !field.is(':password'))
          field.val('').removeClass(cfg.blurClass).addClass(cfg.activeClass);

        if(field.attr('name') == 'url' && field.val() == '')
          field.val('http://').removeClass(cfg.blurClass).addClass(cfg.activeClass);
      });

      field.blur(function(){   
        if((field.val() == '') || (field.attr('name') == 'url' && field.val() == 'http://')){
          if(field.is(':password') && has_pwd_label){
            field.hide();
            pwd_label.show();
          }else{
            field.val(placeholder).removeClass(cfg.activeClass).addClass(cfg.blurClass);
          }
        }else{
          field.removeClass(cfg.blurClass).addClass(cfg.activeClass);
        }
      });

      field.blur();

    });
  };
})(jQuery);



// check if a field has been filled with other than default values (clears the default values)
(function($){
  $.fn.clearFieldCheck = function(){
    return this.each(function(){
      var field = $(this);
      if(field.val() == (field.data('default') || 'http://')) field.val('');

      if(field.is(':password')){
        field.next('.pass-label').hide();
        field.show();
      }

    });
  };
})(jQuery);



// set up quote/reply/voting on a comments area
(function($){
  $.fn.commentControls = function(){
    return this.each(function(){

      var comments = $(this);

      // update avatar on e-mail change
      comments.delegate('#email', 'change', function(){

        $.ajax({
          url: blog_url,
          type: 'GET',
          context: this,
          data: ({
            atom: 'get_avatar',
            email: $(this).val(),
            name: comments.find('#name').val()
          }),
          success: function(data){
            if(data != '') comments.find('.comment.new .avatar').html(data);
          }
        });
      });

      // reply link
      comments.delegate('.comment-reply', 'click', function(event){
        event.preventDefault();

        var data = $(this).attr('id'),
            pos = data.lastIndexOf('-'),
            targetID = data.substr(++pos);

        comments.find('.comment.new').hide();
        comments.find('#comment_parent').attr('value', targetID);

        comments.find('#cancel-reply').show();
        comments.find('.comment.new').appendTo('#comment-body-' + targetID).show(0, function(){

          // move cursor in textarea, at the end of the text
          comments.find('#comment').each(function(){
            if(this.createTextRange){
              var r = this.createTextRange();
              r.collapse(false);
              r.select();
            }
            $(this).focus();
          });

        });
      });

      // cancel reply link
      comments.delegate('#cancel-reply', 'click', function(event){
        event.preventDefault();

        comments.find('.comment.new').hide();
        comments.find('#comment_parent').attr('value','0');

        $(this).hide();
        comments.find('.comment.new').appendTo(comments.find('li.new')).show(0, function(){

          // move cursor in textarea, at the end of the text
          comments.find('#comment').each(function(){
            if(this.createTextRange) {
              var r = this.createTextRange();
              r.collapse(false);
              r.select();
            }
              $(this).focus();
          });

        });
      });

      // quote link
      comments.delegate('.comment-quote', 'click', function(event){
        var textarea = comments.find('#comment'),
            comment = $(this).parents('.comment');

        event.preventDefault();
        textarea.clearFieldCheck();

        // http://phpjs.org/functions/strip_tags:535
        var strip_tags = function(input, allowed){
              allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
              var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
                  commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;

              return input.replace(commentsAndPhpTags, '').replace(tags, function($0, $1){
                return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
              });
            },

            // http://phpjs.org/functions/trim:566
            trim = function(str, charlist){
              var whitespace, l = 0, i = 0;
                  str += '';

              if(!charlist){
                // default list
                whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
              }else{
                // preg_quote custom list
                charlist += '';
                whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
              }

              l = str.length;
              for(i = 0; i < l; i++)
                if(whitespace.indexOf(str.charAt(i)) === -1){
                  str = str.substring(i);
                  break;
                }

              l = str.length;
              for(i = l - 1; i >= 0; i--)
                if(whitespace.indexOf(str.charAt(i)) === -1){
                  str = str.substring(0, i + 1);
                  break;
                }

              return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
            };

        // append value to a input field
        jQuery.fn.appendVal = function(txt){ return this.each(function(){ this.value += txt; }); };

        textarea.appendVal(
          '<blockquote>\n<a href="'
          + $('.comment-id', comment).attr('href') + '">\n<strong><em>'
          + $('.comment-author', comment).html()
          + ':</em></strong>\n</a>\n '
          + trim(strip_tags($('.comment-text', comment).html(), '<em><strong><i><b><a><code>')) + '\n</blockquote>\n'
        );

        textarea.clearFieldCheck();
        textarea.focus();
      });

      // karma vote
      comments.delegate('a.vote', 'click', function(event){
        event.preventDefault();

        $.ajax({
          url: blog_url,
          type: 'GET',
          context: this,
          data:({
            atom: 'comment_karma',
            karma: $(this).data('vote')
          }),
          success: function(data){
            var status = $(this).parent().find('.karma');
            status.html(data);
            if(parseInt(data) > 0){
              status.removeClass('negative');
              status.addClass('positive');
            }
            else if(parseInt(data) < 0){
              status.removeClass('positive');
              status.addClass('negative');
            }
            $(this).parent().find('a').remove();
          }
        });
      });

      // show buried comment
      comments.delegate('a.show', 'click', function(event){
        event.preventDefault();

        $.ajax({
          url: blog_url,
          type: 'GET',
          context: this,
          data:({
            atom: 'get_comment',
            comment_id: $(this).data('comment')
          }),
          success: function(data){
            var comment = $('<ul />').html(data),
                commentbody = comment.find(".comment-body").hide(),
                commentbodyOuterHTML = commentbody[0].outerHTML || commentbody.clone().appendTo('<div>').parent().html();

            $(this).parents('.comment-head').after(commentbodyOuterHTML);

            if($('body').hasClass('no-fx')){
              $(this).parents('li').find('.comment-body').show();
              $(this).parents('.sections').height(comments.height() + 15);

            }else{
              $(this).parents('li').find('.comment-body').animate({
                'opacity': 'show',
                'height': 'show',
                'marginTop': 'show',
                'marginBottom': 'show',
                'paddingTop': 'show',
                'paddingBottom': 'show'
              }, { duration: 333,

                /*/ cool, but too slow...
                step: function(now, fx){
                  $(this).parents('.sections').height(comments.height() + 15);
                }
                //*/

                complete: function(){
                  $(this).parents('.sections').height(comments.height() + 15);
                }
              });
            };
            $(this).remove();
          }
        });
      });


    });

  };

})(jQuery);



// show/hide a element
//  the link's rel attribute should contain the target element ID to toggle
(function($){
  $.fn.toggleVisibility = function(){
    return this.live('click', function(){
      event.preventDefault();
      var target = $('#' + $(this).data('target'));

      if($('body').hasClass('no-fx')) return $(target).toggle(0);
      return $.support.opacity ? $(target).animate({opacity: 'toggle', height: 'toggle'}, 333,  'easeOutQuart') : $(target).animate({height: 'toggle'}, 333, 'easeOutQuart');
    });

  };

})(jQuery);



// display the website screenshot on when mouse over the link
// @todo: handle "no-fx"
(function($){
  $.fn.webShots = function(){
    return this.each(function(i){
      var title = $(this).attr('title'),
          url = 'http://s.wordpress.com/mshots/v1/' + encodeURIComponent($(this).attr('href')) + '?w=400',
          // defaultimg = 'http://s.wordpress.com/wp-content/plugins/mshots/default.gif',
          webshot = $('<div class="webshot" id="webshot-' + i + '"><img src="' + url + '" width="400" alt="' + title + '" /></div>').hide().appendTo(document.body),
          fadeAmt = $('body').hasClass('no-fx') ? 0 : 333;

      /*/
      setTimeout(function(){
        webshot.find('img').attr('src', function(i, oldSrc){
          return oldSrc + '&_=reload';
      });
      }, 10000);
      //*/

      return $(this).mouseover(function(){
        webshot.show();       // trick to avoid problems when using fade effect:  webshot.css({ opacity: 1, display: 'none'}).fadeIn(fadeAmt);
      }).mousemove(function(kmouse){
        webshot.css({
          left: kmouse.pageX + 15,
          top: kmouse.pageY + 15
        });
      }).mouseout(function(){
        webshot.hide();       // or fadeOut(fademt)
      });

    });

  };

})(jQuery);


// set up a "go to top" scroll on this element
(function($){
  $.fn.goTopControl = function(){
    return this.each(function(i){
      var link = $(this);

      $(window).scroll(function(){ // on window scroll
        // stupid IE hack
        if(!$.support.hrefNormalized) link.css({'position': 'absolute', 'top': $(window).scrollTop() + $(window).height() - 50});

        if($(window).scrollTop() >= 500) link.fadeIn(200); else link.fadeOut(200);
      });

      link.live('click', function(){ // on go-to-top click
		$('html,body').animate({ scrollTop: 0 }, 'slow');
        return false;
      });

    });

  };

})(jQuery);



// wrapper for the "Show more" link inside various widgets that use ajax
(function($){
  $.fn.showMoreControl = function(instance, action, nonce){
    return this.each(function(i){

      var block = $(this);

      $('a.more', this).click(function(event){

        event.preventDefault();

        var offset = parseInt($(this).data('count')),
            link = $(this);

        $.ajax({
          type: 'GET',
          url: blog_url, // this variable needs to be set first
          data: {
            instance: instance,
            atom: action,
            offset: offset,
            _ajax_nonce: nonce
          },
          dataType: 'json',
          context: this,
          beforeSend: function(){
            $(this).addClass('loading');
          },
          complete: function(){
            $(this).removeClass('loading');
          },
          success: function(response){

            // append to list & update tab container height (if we're inside a tabbed widget)
            if(response.output != '')

              if($('body').hasClass('no-fx')){ // no effects?
                $(response.output).appendTo(block.find('ul'));
                link.parents('.sections').height(block.height());  // +40 to compensate for tab navi

              }else{
                $(response.output).appendTo(block.find('ul')).hide().each(function(i){
                  $(this).delay(333*i).animate({
                    'opacity': 'show',
                    'height': 'show',
                    'marginTop': 'show',
                    'marginBottom': 'show',
                    'paddingTop': 'show',
                    'paddingBottom': 'show'
                  },
                  { duration: 333,
                    step: function(now, fx){ link.parents('.sections').height(block.height()); }
                  });
                });

              };

            link.data('count', response.offset);

            // no more data?
            if(!response.more) link.hide();

          }
        });

      });

    });

  };

})(jQuery);



// simple nudge effect for links inside a element
// @todo make this live
(function($){
  $.fn.nudgeLinks = function(){
    return this.each(function(i){

      var direction = $(this).data('dir'),
          property = 'margin' + direction.charAt(0).toUpperCase() + direction.slice(1),
          amount = -(parseInt($(this).data('amt'))),
          duration = 166;

      $('a', this).each(function(){
        var link = $(this),
            initialValue = link.css(property),
            go = {},
            bk = {};

        go[property] = amount + parseInt(initialValue);
        bk[property] = initialValue;

        link.hover(function(){
          link.stop().animate(go, duration);
        },
        function(){
          link.stop().animate(bk, duration);
        });

      });

    });

  };

})(jQuery);



// simple fade effect for links inside a element (live)
// basically it appends a <span> inside links and fades it on mouse over/out; the css should take care of styling the span just like a:hover
(function($){
  $.fn.fadeLinks = function(){

    if(!$.support.opacity || !window.XMLHttpRequest) return;

    return this.each(function(){

      $(this).delegate('a', 'mouseover', function(i){
        var span = $(this).children('span.hover');
        if(span.length === 0) span = $('<span class="hover"></span>').appendTo(this).css('opacity', 0);

        span.stop().fadeTo(200, 1);
      });

      $(this).delegate('a', 'mouseout', function(i){
        $(this).children('span.hover').stop().fadeTo(800, 0);
      });

    });

  };

})(jQuery);



// image slider -- this is a improved version of http://webdevkit.net/ubillboard/
// @todo: make delay directly proportional with the square/stripe size
(function($){
  $.fn.imageSlider = function(cfg){

    cfg = $.extend({
      width: false,
      height: false,
      squareSize: 80,  // = 12 x 12 on 960x320
      stripeWidth: 80, // = 4 columns on 960x320
      showPager: true,
      showArrows: true,
      autoplay: true,
      transition: 'random',
      delay: 10        // in seconds
    }, cfg);

    return this.each(function(){

      // set w/h from css if not defined
      cfg.width = cfg.width || $(this).width();
      cfg.height = cfg.height || $(this).height();

      // minimum 47px, max 188px
      cfg.squareSize = Math.min(Math.max(cfg.squareSize, 47), 188);
      cfg.stripeWidth = Math.min(Math.max(cfg.stripeWidth, 30), 188);
      cfg.delay = (parseInt($(this).data('delay'), 10) * 1000) || (cfg.delay * 1000);

      var loader = $('<div class="loading"></div>').css({
            left: cfg.width / 2 - 80,
            top: cfg.height / 2 - 10
          }),
          controls = $('<div class="i-controls"></div>'),
          nextSlide = $('<div class="next-slide"></div>'),
          link = $('<a href="" class="link"></a>').hide().appendTo(controls),
          block = $(this).prepend(nextSlide).append(controls).prepend(loader),

          slides = [],                                           // global slides array
          currentSlideIndex = 0,                                 // slide currently in nextSlide
          prevSlideIndex = 0,                                    // slide in background
          totalImages = $('.slide', block).length,               // image count
          totalImagesLoaded = 0,
          timeout = null,
          playing = (typeof block.data('autoplay') !== 'undefined') ? block.data('autoplay') : cfg.autoplay, // holds current play/pause status
          playState = false,

          squareRows = Math.ceil(cfg.height / cfg.squareSize),   // number of square rows
          squareCols = Math.ceil(cfg.width / cfg.squareSize),    // number of square columns
          stripeCols = Math.ceil(cfg.width / cfg.stripeWidth),   // number of stripe columns

          // animation functions
          animations = {

            animationFade: function(currentIndex, destinationIndex, callback){
              nextSlide.css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0
              }).animate({
                opacity: 1
              }, {
                duration: 1333,
                complete: callback,
                easing: 'easeOutSine'
              });
            },

            animationSlideH: function(currentIndex, destinationIndex, callback, reverse){
              nextSlide.css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                left: cfg.width
              }).animate({
                left: 0
              }, {
                duration: 999,
                complete: callback,
                easing: 'easeOutExpo'
              });
            },

            animationSlideV: function(currentIndex, destinationIndex, callback, reverse){
              nextSlide.css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                top: reverse ? cfg.height : (- cfg.height)
              }).animate({
                top: 0
              }, {
                duration: 999,
                complete: callback,
                easing: 'easeOutExpo'
              });
            },

            animationRandomTiles: function(currentIndex, destinationIndex, callback){

              // create a array containing delay values for each element
              for(var delayTable = [], i = 0; i < (squareRows * squareCols - 1); ++i) delayTable[i] =  20 * i;

              // shuffle it
              for(var j, x, i = delayTable.length; i; j = parseInt(Math.random() * i), x = delayTable[--i], delayTable[i] = delayTable[j], delayTable[j] = x){};

              $('.square', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0
              }).each(function(i){
                $(this).stop().delay(delayTable[i]).animate({
                  opacity: 1
                }, {
                  duration: 999,
                  easing: 'easeOutQuad',
                  complete: (Math.max.apply(Math, delayTable) !== delayTable[i]) || callback
                });
              });

            },

            animationHorizontalTiles: function(currentIndex, destinationIndex, callback, reverse){
              var end = reverse ? 0 : (squareRows * squareCols - 1);

              // delay: 4x10 > 30  20x8 > 5
              $('.square', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0
              }).each(function(i){
                $(this).stop().delay(30 * (reverse ? (squareRows * squareCols - i) : i)).animate({
                  opacity: 1
                }, {
                  duration: 666,
                  easing: 'easeOutSine',
                  complete: (i !== end) || callback
                });
              });
            },

            animationDiagonalTiles: function(currentIndex, destinationIndex, callback, reverse){
              var n = 0,
                  end = reverse ? 0 : ((squareRows * squareCols) - 1);

              $('.square', nextSlide).css({
                backgroundImage: 'url(' + slides[reverse ? destinationIndex : currentIndex].image + ')',
                opacity: reverse ? 0 : 1
              });

              if(reverse) _resetSquares(-20, -20); else nextSlide.css('background-image', 'url(' + slides[destinationIndex].image + ')');

              block.removeClass('no-overflow');

              for(var y = 0; y < squareRows; y++)
                for(var x = 0; x < squareCols; x++){
                  $('.square-' + n, nextSlide).stop().delay(100 * (reverse ? (squareRows - y + squareCols - x) : (x + y))).animate({
                    opacity: reverse ? 1 : 0,
                    left: reverse ? (x * cfg.squareSize) : (x * cfg.squareSize - 20),
                    top: reverse ? (y * cfg.squareSize) : (y * cfg.squareSize - 20)
                  }, {
                    duration: 333,
                    complete: (n !== end) || callback
                  });
                  ++n;
                }

            },

            animationSpiral: function(currentIndex, destinationIndex, callback, reverse){
              var order = [], rowsHalf = Math.ceil(squareRows/2), x, y, z, n = 0;

              // create a spiral matrix
              for(z = 0; z < rowsHalf; z++){
                y = z;
                for(x = z; x < squareCols - z - 1; x++) order[n++] = y * squareCols + x;

                x = squareCols - z - 1;
                for(y = z; y < squareRows - z - 1; y++) order[n++] = y * squareCols + x;

                y = squareRows - z - 1;
                for(x = squareCols - z - 1; x > z; x--) order[n++] = y * squareCols + x;

                x = z;
                for(y = squareRows - z - 1; y > z; y--) order[n++] = y * squareCols + x;
              };

              if(reverse) order.reverse();

              for(var m = 0; m < n; m++)
                $('.square-' + order[m], nextSlide).css({
                  backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                  opacity: 0
                }).each(function(i){
                  $(this).stop().delay(30*m).animate({
                    opacity: 1
                  }, {
                    duration: 666,
                    easing: 'easeOutSine',
                    complete: (m != n - 1) || callback
                  });
                });

            },

            animationRandomStripes: function(currentIndex, destinationIndex, callback){
              // create a array containing delay values for each element
              for(var delayTable = [], i = 0; i < (stripeCols - 1); ++i) delayTable[i] =  60 * i;

              // shuffle it
              for(var j, x, i = delayTable.length; i; j = parseInt(Math.random() * i), x = delayTable[--i], delayTable[i] = delayTable[j], delayTable[j] = x){};

              $('.stripe', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0,
                top: -40
              });

              for(var i = 0; i < stripeCols; i++){
                $('.stripe-' + i, nextSlide).stop().delay(delayTable[i]).animate({
                  opacity: 1,
                  top: 0
                }, {
                  duration: 999,
                  specialEasing: {
                    opacity: 'easeOutQuad',
                    top: 'easeOutElastic'
                  },
                  complete: (Math.max.apply(Math, delayTable) !== delayTable[i]) || callback
                });
              }
            },

            animationStripeWave: function(currentIndex, destinationIndex, callback, reverse){
              var end = reverse ? 0 : (stripeCols - 1);
              $('.stripe', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0,
                top: - 30
              });

              block.removeClass('no-overflow');

              for(var i = 0; i < stripeCols; i++){
                $('.stripe-' + i, nextSlide).stop().delay(30 * (reverse ? (stripeCols - i) : i)).animate({
                  opacity: 1,
                  top: 0
                }, {
                  duration: 999,
                  specialEasing: {
                    opacity: 'easeOutSine',
                    top: 'easeOutElastic'
                  },
                  complete: (i !== end) || callback
                });
              }
            },

            animationCurtain: function(currentIndex, destinationIndex, callback, reverse){
              var end = reverse ? 0 : (stripeCols - 1);

              $('.stripe', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0,
                height: 0,
                top: -(cfg.height / 2)
              });

              block.removeClass('no-overflow');

              for(var i = 0; i < stripeCols; i++){
                $('.stripe-' + i, nextSlide).stop().delay(70 * (reverse ? (stripeCols - i) : i)).animate({
                  opacity: 1,
                  height: cfg.height,
                  top: 0
                }, {
                  duration: 333,
                  specialEasing: {
                    opacity: 'easeInSine',
                    height: 'easeOutQuad',
                    top: 'easeOutQuad'
                  },
                  complete: (i !== end) || callback
                });
              }

            },

            animationInterweave: function(currentIndex, destinationIndex, callback, reverse){
              var end = reverse ? 0 : (stripeCols - 1);

              $('.stripe', nextSlide).css({
                backgroundImage: 'url(' + slides[destinationIndex].image + ')',
                opacity: 0
              });

              $('.stripe:even', nextSlide).css('top', - cfg.height);
              $('.stripe:odd', nextSlide).css('top', cfg.height);

              block.removeClass('no-overflow');

              for(var i = 0; i < stripeCols; i++){
                $('.stripe-' + i, nextSlide).stop().delay(50 * (reverse ? (stripeCols - i) : i)).animate({
                  opacity: 1,
                  top: 0
                }, {
                  duration: 666,
                  specialEasing: {
                    opacity: 'easeOutSine',
                    top: 'easeOutExpo'
                  },
                  complete: (i !== end) || callback
                });
              }

            }

          },

          // check if anything is being animated
          isAnimating = function(){
            return nextSlide.is(':animated') || $('div', nextSlide).is(':animated') || $('.caption', controls).is(':animated');
          },

          // switches the current slide with the next slide
          _showSlide = function(index, reverse){
            clearTimeout(timeout);
            prevSlideIndex = currentSlideIndex;
            currentSlideIndex = index;
            block.css('background-image', 'url(' + slides[prevSlideIndex].image + ')');
            link.hide();

            $('.pager a', controls).removeClass('current');
            $('.pager a:eq(' + currentSlideIndex + ')', controls).addClass('current');

            _hideDescription();

            var getRandomTransition = function(){
                  var count = 0,
                      result;
                  for(var prop in animations) if (Math.random() < 1 / ++count) result = prop;
                  return result;
                },

                transition = (slides[currentSlideIndex].transition != 'random') ? animations['animation' + slides[currentSlideIndex].transition] : animations[getRandomTransition()];

            transition(prevSlideIndex, currentSlideIndex, function(){
                block.removeClass('no-overflow').addClass('no-overflow').css('background-image', 'url(' + slides[currentSlideIndex].image + ')');
                $('div', nextSlide).add(nextSlide).css('background-image', '');
                _resetSquares(0, 0);
                _resetStripes();
                _showDescription(currentSlideIndex);

                // change link's href and triggeer a custom event to let the lightbox know about this
                if(slides[currentSlideIndex].link)
                  link.attr('href', slides[currentSlideIndex].link).show().trigger('href_updated');

                if(!playing) return;
                _setupTimeout();
              },
              reverse
            );
          },

          _setupTimeout = function(){
            timeout = setTimeout(function(){
              var index = typeof slides[currentSlideIndex + 1] == 'undefined' ? 0 : currentSlideIndex + 1;
              _showSlide(index);
            }, slides[currentSlideIndex].delay);
          },

          // shows description, create it if necessary
          _showDescription = function(current){

            // normally the 2nd condition should never be checked, but I encountered some flicker in a few rare cases so we leave it until I find the issues...
            var caption = ($('.caption', controls).length === 0) ? $(slides[current].caption).appendTo(controls) : $('.caption', controls).replaceAll($(slides[current].caption));
			caption.css({
				opacity: 0
			}).stop().show().animate({
				opacity: 1
			}, {
				duration: 333
			});
          },

          // hide description
          _hideDescription = function(){

            var caption = $('.caption', controls);

            if(caption.hasClass('push-left')){
              caption.stop().animate({
                opacity: 0,
                left: - (0.3 * cfg.width)
              }, {
                duration: 333,
                easing: 'easeOutExpo',
                complete: function(){ caption.remove(); }
              });
            }else if(caption.hasClass('push-right')){
              caption.stop().animate({
                right: - (0.3 * cfg.width),
                opacity: 0
              }, {

                duration: 333,
                easing: 'easeOutExpo',
                complete: function(){ caption.remove(); }
              });
            }else{
              caption.stop().animate({
                opacity: 0,
                bottom: - caption.outerHeight()
              }, {
                duration: 333,
                easing: 'easeOutExpo',
                complete: function(){ caption.remove(); }
              });
            }
          },

          _resetSquares = function(offsetX, offsetY){

            for(var y = 0; y < squareRows; y++)
              for(var x = 0; x < squareCols; x++)
                $('.square-' + (squareCols * y + x), nextSlide).css({
                  backgroundPosition: - x * cfg.squareSize + 'px ' + (- y * cfg.squareSize) + 'px',
                  backgroundRepeat: 'no-repeat',
                  position: 'absolute',
                  left: x * cfg.squareSize + offsetX,
                  top: y * cfg.squareSize + offsetY,
                  opacity: 0,
                  width: cfg.squareSize,
                  height: cfg.squareSize
                });
          },

          _resetStripes = function(){
            for(var i = 0; i < stripeCols; i++){
              $('.stripe-' + i, nextSlide).css({
                backgroundPosition: - i * cfg.stripeWidth + 'px 0',
                backgroundRepeat: 'no-repeat',
                position: 'absolute',
                left: i * cfg.stripeWidth,
                top: 0,
                opacity: 0,
                width: cfg.stripeWidth,
                height: cfg.height
              });
            }
          };


      // process each slide
      $('.slide', block).each(function(i, el){
        var slide = {
              delay: (parseInt($(this).data('delay')) * 1000) || cfg.delay,
              transition: $(this).data('fx') || cfg.transition,
              link: $('img:first', this).parent('a').attr('href') || '',
              image: $('img:first', this).attr('src'),
              caption: $('.caption', this).clone().wrap('<div></div>').parent().html()
            };

        slides.push(slide);

        // preloader
        $('<img>', this).load(function(){

          ++totalImagesLoaded;

          if(totalImages === totalImagesLoaded){
            block.css('background-image', 'url(' + slides[0].image + ')').addClass('no-overflow');

            if(slides[0].link)
              link.attr('href', slides[0].link).show().trigger('href_updated');

            $('.slide', block).remove();
            loader.remove();

            // button controls
            if(block.data('controls')){ // html5 data-controls attribute overrides defaults
              var items = block.data('controls').replace(/ /g, '').split(',');
              cfg.showPager = !!~$.inArray('pager', items);
              cfg.showArrows = !!~$.inArray('arrows', items);
            };

            // previous/next arrow buttons
            if(cfg.showArrows){

              $('<a>', {
                'class': 'prev',
                'css': { top: cfg.height/2 - 48, opacity: 0 },
                'click': function(){
                  if(isAnimating()) return;
                  var index = currentSlideIndex - 1;
                  if(typeof slides[index] == 'undefined') index = totalImages - 1;
                  _showSlide(index, true);
                  return false;
                }
              }).appendTo(controls);

              $('<a>', {
                'class': 'next',
                'css': { top: cfg.height/2 - 48, opacity: 0 },
                'click': function(){
                  if(isAnimating()) return;
                  var index = currentSlideIndex + 1;
                  if(typeof slides[index] == 'undefined') index = 0;
                  _showSlide(index);
                  return false;
                }
              }).appendTo(controls);

            };

            // pagination
            if(cfg.showPager){

              var current = 0,
                  pager = $('<div>', {
                    'class': 'pager',
                    'css': { opacity: 0 }
                  }).appendTo(controls);

              for(var i = 0; i < totalImages; i++)
                $('.pager', controls).append($('<a'+ (i == current ? ' class="current"' : '') + '>' + (i + 1) + '</a>'));

              $('.pager a', controls).click(function(){
                if($(this).index() == currentSlideIndex || isAnimating()) return false;
                clearInterval(timeout);
                _showSlide($(this).index(), (currentSlideIndex > $(this).index()));
                return false;
              });

            };

            controls.hover(function(){
              $('.pager, a.next, a.prev', controls).stop().animate({opacity: 1}, 333);
              // pause on mouseover / unpause on mouseout
              clearInterval(timeout);
              if(playing){
                playState = true;
                playing = false;
              }
            }, function(){
              $('.pager, a.next, a.prev', controls).stop().animate({opacity: 0}, 666);
              if(playState){
                _setupTimeout();
                playing = true;
              }
            });

            _showDescription(0);

            // set up squares
            for(var i = 0; i < (squareRows * squareCols); i++) nextSlide.append($('<div />').addClass('square square-' + i));
            _resetSquares(0, 0);

            // set up stripes
            for(var i = 0; i < stripeCols; i++) nextSlide.append($('<div />').addClass('stripe stripe-' + i));
            _resetStripes();

            controls.fadeIn(333);

            if(totalImages < 2 || !playing) return;
            _setupTimeout();

          }
        }).attr('src', slide.image);
      });

    });

  };
})(jQuery);



/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
jQuery.cookie = function(name, value, options){
  if(typeof value != 'undefined'){ // name and value given, set cookie
    options = options || {};
    if(value === null){
      value = '';
      options.expires = -1;
    }
    var expires = '';
    if(options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)){
      var date;
      if(typeof options.expires == 'number'){
        date = new Date();
        date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
      }else{
        date = options.expires;
      }
      expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
    }

    // CAUTION: Needed to parenthesize options.path and options.domain
    // in the following expressions, otherwise they evaluate to undefined
    // in the packed version for some reason...
    var path = options.path ? '; path=' + (options.path) : '',
        domain = options.domain ? '; domain=' + (options.domain) : '',
        secure = options.secure ? '; secure' : '';
    document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');

  }else{ // only name given, get cookie
    var cookieValue = null;
    if(document.cookie && document.cookie != ''){
      var cookies = document.cookie.split(';');
      for(var i = 0; i < cookies.length; i++){
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if(cookie.substring(0, name.length + 1) == (name + '=')){
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
};







/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 *
 * Open source under the BSD License.
 *
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});


  








/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (MIT_LICENSE.txt)
 * and GPL Version 2 (GPL_LICENSE.txt) licenses.
 *
 * Version: 1.1.1
 * Requires jQuery 1.3+
 * Docs: http://docs.jquery.com/Plugins/livequery
 */

(function($) {

$.extend($.fn, {
	livequery: function(type, fn, fn2) {
		var self = this, q;

		// Handle different call patterns
		if ($.isFunction(type))
			fn2 = fn, fn = type, type = undefined;

		// See if Live Query already exists
		$.each( $.livequery.queries, function(i, query) {
			if ( self.selector == query.selector && self.context == query.context &&
				type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
					// Found the query, exit the each loop
					return (q = query) && false;
		});

		// Create new Live Query if it wasn't found
		q = q || new $.livequery(this.selector, this.context, type, fn, fn2);

		// Make sure it is running
		q.stopped = false;

		// Run it immediately for the first time
		q.run();

		// Contnue the chain
		return this;
	},

	expire: function(type, fn, fn2) {
		var self = this;

		// Handle different call patterns
		if ($.isFunction(type))
			fn2 = fn, fn = type, type = undefined;

		// Find the Live Query based on arguments and stop it
		$.each( $.livequery.queries, function(i, query) {
			if ( self.selector == query.selector && self.context == query.context &&
				(!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
					$.livequery.stop(query.id);
		});

		// Continue the chain
		return this;
	}
});

$.livequery = function(selector, context, type, fn, fn2) {
	this.selector = selector;
	this.context  = context;
	this.type     = type;
	this.fn       = fn;
	this.fn2      = fn2;
	this.elements = [];
	this.stopped  = false;

	// The id is the index of the Live Query in $.livequery.queries
	this.id = $.livequery.queries.push(this)-1;

	// Mark the functions for matching later on
	fn.$lqguid = fn.$lqguid || $.livequery.guid++;
	if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;

	// Return the Live Query
	return this;
};

$.livequery.prototype = {
	stop: function() {
		var query = this;

		if ( this.type )
			// Unbind all bound events
			this.elements.unbind(this.type, this.fn);
		else if (this.fn2)
			// Call the second function for all matched elements
			this.elements.each(function(i, el) {
				query.fn2.apply(el);
			});

		// Clear out matched elements
		this.elements = [];

		// Stop the Live Query from running until restarted
		this.stopped = true;
	},

	run: function() {
		// Short-circuit if stopped
		if ( this.stopped ) return;
		var query = this;

		var oEls = this.elements,
			els  = $(this.selector, this.context),
			nEls = els.not(oEls);

		// Set elements to the latest set of matched elements
		this.elements = els;

		if (this.type) {
			// Bind events to newly matched elements
			nEls.bind(this.type, this.fn);

			// Unbind events to elements no longer matched
			if (oEls.length > 0)
				$.each(oEls, function(i, el) {
					if ( $.inArray(el, els) < 0 )
						$.event.remove(el, query.type, query.fn);
				});
		}
		else {
			// Call the first function for newly matched elements
			nEls.each(function() {
				query.fn.apply(this);
			});

			// Call the second function for elements no longer matched
			if ( this.fn2 && oEls.length > 0 )
				$.each(oEls, function(i, el) {
					if ( $.inArray(el, els) < 0 )
						query.fn2.apply(el);
				});
		}
	}
};

$.extend($.livequery, {
	guid: 0,
	queries: [],
	queue: [],
	running: false,
	timeout: null,

	checkQueue: function() {
		if ( $.livequery.running && $.livequery.queue.length ) {
			var length = $.livequery.queue.length;
			// Run each Live Query currently in the queue
			while ( length-- )
				$.livequery.queries[ $.livequery.queue.shift() ].run();
		}
	},

	pause: function() {
		// Don't run anymore Live Queries until restarted
		$.livequery.running = false;
	},

	play: function() {
		// Restart Live Queries
		$.livequery.running = true;
		// Request a run of the Live Queries
		$.livequery.run();
	},

	registerPlugin: function() {
		$.each( arguments, function(i,n) {
			// Short-circuit if the method doesn't exist
			if (!$.fn[n]) return;

			// Save a reference to the original method
			var old = $.fn[n];

			// Create a new method
			$.fn[n] = function() {
				// Call the original method
				var r = old.apply(this, arguments);

				// Request a run of the Live Queries
				$.livequery.run();

				// Return the original methods result
				return r;
			}
		});
	},

	run: function(id) {
		if (id != undefined) {
			// Put the particular Live Query in the queue if it doesn't already exist
			if ( $.inArray(id, $.livequery.queue) < 0 )
				$.livequery.queue.push( id );
		}
		else
			// Put each Live Query in the queue if it doesn't already exist
			$.each( $.livequery.queries, function(id) {
				if ( $.inArray(id, $.livequery.queue) < 0 )
					$.livequery.queue.push( id );
			});

		// Clear timeout if it already exists
		if ($.livequery.timeout) clearTimeout($.livequery.timeout);
		// Create a timeout to check the queue and actually run the Live Queries
		$.livequery.timeout = setTimeout($.livequery.checkQueue, 1000);
	},

	stop: function(id) {
		if (id != undefined)
			// Stop are particular Live Query
			$.livequery.queries[ id ].stop();
		else
			// Stop all Live Queries
			$.each( $.livequery.queries, function(id) {
				$.livequery.queries[ id ].stop();
			});
	}
});

// Register core DOM manipulation methods
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html');

// Run Live Queries when the Document is ready
$(function() { $.livequery.play(); });

})(jQuery);









/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt

 // note: modified for ATOM - careful if you're updating this plugin!

 */
;(function($){
  $.fn.superfish = function(op){
    var sf = $.fn.superfish,
        c = sf.c,
        $arrow = $(['<span class="', c.arrowClass, '">&nbsp;</span>'].join('')),
        over = function(){
          var menu = getMenu($(this));
          clearTimeout(menu.sfTimer);
          $(this).showSuperfishUl().siblings().hideSuperfishUl();
          },
        out = function(){
          var menu = getMenu($(this)),
              that = $(this),
              o = sf.op;
          clearTimeout(menu.sfTimer);
          menu.sfTimer = setTimeout(function(){
            o.retainPath = ($.inArray(that[0], o.path) > -1);
            that.hideSuperfishUl();
            if (o.path.length && that.parents(['li.', o.hoverClass].join('')).length < 1)  over.call(o.path);
          }, o.delay);
        },
        getMenu = function($menu){
          var menu = $menu.parents(['ul.', c.menuClass, ':first'].join(''))[0];
          sf.op = sf.o[menu.serial];
          return menu;
        },
        addArrow = function($a){
          $a.addClass(c.anchorClass).append($arrow.clone());
        };

    return this.each(function(){
      var s = this.serial = sf.o.length;
      var o = $.extend({}, sf.defaults, op);

      if($('body').hasClass('no-fx')) o.fx = false;

      if(o.fx){
        if($(this).hasClass('slide-up')) o.dir = "marginBottom";
        if($(this).hasClass('slide-left')) o.dir = "marginLeft";
        if($(this).hasClass('slide-right')) o.dir = "marginRight";
      };

      o.path = $('li.' + o.pathClass, this).slice(0, o.pathLevels).each(function(){
        $(this).addClass([o.hoverClass, c.bcClass].join(' ')).filter('li:has(ul)').removeClass(o.pathClass);
      });
      sf.o[s] = sf.op = o;
      $('li:has(ul)', this)['hover'](over, out).each(function(){
        if (o.autoArrows) addArrow($('>a:first-child', this));
      }).not('.' + c.bcClass).hideSuperfishUl();

      var link = $('a', this);
      link.each(function(i){
        var link_li = link.eq(i).parents('li');
        link.eq(i).focus(function(){ over.call(link_li); }).blur(function(){ out.call(link_li); });
      });
    }).each(function(){
      var menuClasses = [c.menuClass];
      $(this).addClass(menuClasses.join(' '));
    });
  };

  var sf = $.fn.superfish;
  sf.o = [];
  sf.op = {};
  sf.c = {
    bcClass: 'breadcrumb',
    menuClass: 'superfish',
    anchorClass: 'has-submenus',
    arrowClass: 'arrow'
  };
  sf.defaults = {
    hoverClass: 'open',
    pathClass: 'overideThisToUse',
    pathLevels: 1,
    delay: 500,
    dir: 'marginTop',
    fx: true,
    autoArrows: true
  };

  $.fn.extend({

    hideSuperfishUl: function(){
      var o = sf.op,
          not = (o.retainPath === true) ? o.path : '';
      o.retainPath = false;
      var menu = $(['li.', o.hoverClass].join(''), this).add(this).not(not).removeClass(o.hoverClass).find('>ul');
      if(o.fx){
        var css = {};
        css[o.dir] = 20;
        if($.support.opacity) css["opacity"] = 0;
        menu.stop().animate(css, 150, 'swing', function(){$(this).css({display: "none" })});
      }else{
        menu.css({display: "none"});
      }
      return this;
    },

    showSuperfishUl: function(){
      var o = sf.op;

      if(o.fx){
        var css1 = {}, css2 = {};
        css1["display"] = "block";
        css1[o.dir] = 20;
        css2[o.dir] = 0;
        if($.support.opacity){
          css1["opacity"] = 0;
          css2["opacity"] = 1;
        };
        $(this).addClass(o.hoverClass).find('>ul:hidden').css(css1).stop().animate(css2, 150, 'swing');
      }else{
        $(this).addClass(o.hoverClass).find('>ul:hidden').css({display: "block"});
      };
      return this;
    }
  });
})(jQuery);




/*
 * FancyBox - jQuery Plugin
 * Simple and fancy lightbox alternative
 *
 * Examples and documentation at: http://fancybox.net
 *
 * Copyright (c) 2008 - 2010 Janis Skarnelis
 * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 *
 * Version: 1.3.4 (11/11/2010)
 * Requires: jQuery v1.3+
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

;(function($) {
	var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right,

		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],

		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,

		titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }),

		/*
		 * Private methods
		 */

		_abort = function() {
			loading.hide();

			imgPreloader.onerror = imgPreloader.onload = null;

			if (ajaxLoader) {
				ajaxLoader.abort();
			}

			tmp.empty();
		},

		_error = function() {
			if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
				loading.hide();
				busy = false;
				return;
			}

			selectedOpts.titleShow = false;

			selectedOpts.width = 'auto';
			selectedOpts.height = 'auto';

			tmp.html( '<p id="fb-error">The requested content cannot be loaded.<br />Please try again later.</p>' );

			_process_inline();
		},

		_start = function() {
			var obj = selectedArray[ selectedIndex ],
				href,
				type,
				title,
				str,
				emb,
				ret;

			_abort();

			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));

			ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);

			if (ret === false) {
				busy = false;
				return;
			} else if (typeof ret == 'object') {
				selectedOpts = $.extend(selectedOpts, ret);
			}

			title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';

			if (obj.nodeName && !selectedOpts.orig) {
				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
			}

			if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
				title = selectedOpts.orig.attr('alt');
			}

			href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;

			if ((/^(?:javascript)/i).test(href) || href == '#') {
				href = null;
			}

			if (selectedOpts.type) {
				type = selectedOpts.type;

				if (!href) {
					href = selectedOpts.content;
				}

			} else if (selectedOpts.content) {
				type = 'html';

			} else if (href) {
				if (href.match(imgRegExp)) {
					type = 'image';

				} else if (href.match(swfRegExp)) {
					type = 'swf';

				} else if (href.indexOf("#") === 0) {
					type = 'inline';

				} else {
					type = 'ajax';
				}
			}

			if (!type) {
				_error();
				return;
			}

			if (type == 'inline') {
				obj	= href.substr(href.indexOf("#"));
				type = $(obj).length > 0 ? 'inline' : 'ajax';
			}

			selectedOpts.type = type;
			selectedOpts.href = href;
			selectedOpts.title = title;

			if (selectedOpts.autoDimensions) {
				if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') {
					selectedOpts.width = 'auto';
					selectedOpts.height = 'auto';
				} else {
					selectedOpts.autoDimensions = false;
				}
			}

			if (selectedOpts.modal) {
				selectedOpts.overlayShow = true;
				selectedOpts.hideOnOverlayClick = false;
				selectedOpts.hideOnContentClick = false;
				selectedOpts.enableEscapeButton = false;
			}

			selectedOpts.padding = parseInt(selectedOpts.padding, 10);
			selectedOpts.margin = parseInt(selectedOpts.margin, 10);

			tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));

			$('.fb-inline-tmp').unbind('fb-cancel').bind('fb-change', function() {
				$(this).replaceWith(content.children());
			});

			switch (type) {
				case 'html' :
					tmp.html( selectedOpts.content );
					_process_inline();
				break;

				case 'inline' :
					if ( $(obj).parent().is('#fb-content') === true) {
						busy = false;
						return;
					}

					$('<div class="fb-inline-tmp" />')
						.hide()
						.insertBefore( $(obj) )
						.bind('fb-cleanup', function() {
							$(this).replaceWith(content.children());
						}).bind('fb-cancel', function() {
							$(this).replaceWith(tmp.children());
						});

					$(obj).appendTo(tmp);

					_process_inline();
				break;

				case 'image':
					busy = false;

					loading.show();

					imgPreloader = new Image();

					imgPreloader.onerror = function() {
						_error();
					};

					imgPreloader.onload = function() {
						busy = true;

						imgPreloader.onerror = imgPreloader.onload = null;

						_process_image();
					};

					imgPreloader.src = href;
				break;

				case 'swf':
					selectedOpts.scrolling = 'no';

					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
					emb = '';

					$.each(selectedOpts.swf, function(name, val) {
						str += '<param name="' + name + '" value="' + val + '"></param>';
						emb += ' ' + name + '="' + val + '"';
					});

					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';

					tmp.html(str);

					_process_inline();
				break;

				case 'ajax':
					busy = false;

					loading.show();

					selectedOpts.ajax.win = selectedOpts.ajax.success;

					ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
						url	: href,
						data : selectedOpts.ajax.data || {},
						error : function(XMLHttpRequest, textStatus, errorThrown) {
							if ( XMLHttpRequest.status > 0 ) {
								_error();
							}
						},
						success : function(data, textStatus, XMLHttpRequest) {
							var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader;
							if (o.status == 200) {
								if ( typeof selectedOpts.ajax.win == 'function' ) {
									ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);

									if (ret === false) {
										loading.hide();
										return;
									} else if (typeof ret == 'string' || typeof ret == 'object') {
										data = ret;
									}
								}

								tmp.html( data );
								_process_inline();
							}
						}
					}));

				break;

			}
		},

		_process_inline = function() {
			var
				w = selectedOpts.width,
				h = selectedOpts.height;

			if (w.toString().indexOf('%') > -1) {
				w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';

			} else {
				w = w == 'auto' ? 'auto' : w + 'px';
			}

			if (h.toString().indexOf('%') > -1) {
				h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';

			} else {
				h = h == 'auto' ? 'auto' : h + 'px';
			}

			tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');

			selectedOpts.width = tmp.width();
			selectedOpts.height = tmp.height();

			_show();
		},

		_process_image = function() {
			selectedOpts.width = imgPreloader.width;
			selectedOpts.height = imgPreloader.height;

			$("<img />").attr({
				'id' : 'fb-img',
				'src' : imgPreloader.src,
				'alt' : selectedOpts.title
			}).appendTo( tmp );

			_show();
		},

		_show = function() {
			var pos, equal;

			loading.hide();

			if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
				$.event.trigger('fb-cancel');

				busy = false;
				return;
			}

			busy = true;

			$(content.add( overlay )).unbind();

			$(window).unbind("resize.fb scroll.fb");
			$(document).unbind('keydown.fb');

			if (wrap.is(":visible")) {
				wrap.css('height', wrap.height());
			}

			currentArray = selectedArray;
			currentIndex = selectedIndex;
			currentOpts = selectedOpts;

			if (currentOpts.overlayShow) {
				overlay.css({
					'opacity' : currentOpts.overlayOpacity,
					'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
					'height' : $(document).height()
				});

				if (!overlay.is(':visible')) {
 					overlay.show();
				}
			} else {
				overlay.hide();
			}

			final_pos = _get_zoom_to();

			_process_title();

			if (wrap.is(":visible")) {
				$(nav_left.add(nav_right)).hide();

				pos = wrap.position(),

				start_pos = {
					top	 : pos.top,
					left : pos.left,
					width : wrap.width(),
					height : wrap.height()
				};

				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);

				content.fadeTo(currentOpts.changeFade, 0.3, function() {
					var finish_resizing = function() {
						content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish);
					};

					$.event.trigger('fb-change');

					content
						.empty()
						.removeAttr('filter')
						.css({
							'border-width' : currentOpts.padding,
							'width'	: final_pos.width - currentOpts.padding * 2,
							'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
						});

					if (equal) {
						finish_resizing();

					} else {
						fx.prop = 0;

						$(fx).animate({prop: 1}, {
							 duration : currentOpts.changeSpeed,
							 easing : currentOpts.easingChange,
							 step : _draw,
							 complete : finish_resizing
						});
					}
				});

				return;
			}

			wrap.removeAttr("style");

			content.css('border-width', currentOpts.padding);

			if (currentOpts.transitionIn == 'elastic') {
				start_pos = _get_zoom_from();

				content.html( tmp.contents() );

				wrap.show();

				if (currentOpts.opacity) {
					final_pos.opacity = 0;
				}

				fx.prop = 0;

				$(fx).animate({prop: 1}, {
					 duration : currentOpts.speedIn,
					 easing : currentOpts.easingIn,
					 step : _draw,
					 complete : _finish
				});

				return;
			}

			if (titleHeight > 0) {
				title.show();
			}

			content
				.css({
					'width' : final_pos.width - currentOpts.padding * 2,
					'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
				})
				.html( tmp.contents() );

			wrap
				.css(final_pos)
				.fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );

		},

		_format_title = function(title) {
			if (title && title.length) {

				return title;
			}

			return false;
		},

		_process_title = function() {
			titleStr = currentOpts.title || '';
			titleHeight = 0;

			title
				.empty()
				.removeAttr('style')
				.removeClass();

			if (currentOpts.titleShow === false) {
				title.hide();
				return;
			}

			titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);

			if (!titleStr || titleStr === '') {
				title.hide();
				return;
			}

			title
				.html( titleStr )
				.appendTo( 'body' )
				.show();

					title
						.css({
							'width' : final_pos.width - (currentOpts.padding * 2),
							'marginLeft' : currentOpts.padding,
							'marginRight' : currentOpts.padding
						});

					titleHeight = title.outerHeight(true);

					title.appendTo( outer );

					final_pos.height += titleHeight;

			title.hide();
		},

		_set_navigation = function() {
			if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
				$(document).bind('keydown.fb', function(e) {
					if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
						e.preventDefault();
						$.fancybox.close();

					} else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
						e.preventDefault();
						$.fancybox[ e.keyCode == 37 ? 'prev' : 'next']();
					}
				});
			}

			if (!currentOpts.showNavArrows) {
				nav_left.hide();
				nav_right.hide();
				return;
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
			    $('a', nav_left).css('top', (wrap.height() / 2 - ($('a', nav_left).height() / 2)));
				nav_left.show();
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
			    $('a', nav_right).css('top', (wrap.height() / 2 - ($('a', nav_left).height() / 2)));
				nav_right.show();
			}
		},

		_finish = function () {
			if (!$.support.opacity) {
				content.get(0).style.removeAttribute('filter');
				wrap.get(0).style.removeAttribute('filter');
			}

			if (selectedOpts.autoDimensions) {
				content.css('height', 'auto');
			}

			wrap.css('height', 'auto');

			if (titleStr && titleStr.length) {
				title.show();
			}

			_set_navigation();

			if (currentOpts.hideOnContentClick)	{
				content.bind('click', $.fancybox.close);
			}

			if (currentOpts.hideOnOverlayClick)	{
				overlay.bind('click', $.fancybox.close);
			}

			$(window).bind("resize.fb", $.fancybox.resize);

			if (currentOpts.centerOnScroll) {
				$(window).bind("scroll.fb", $.fancybox.center);
			}

			wrap.show();

			busy = false;

			$.fancybox.center();

			currentOpts.onComplete(currentArray, currentIndex, currentOpts);

			_preload_images();
		},

		_preload_images = function() {
			var href,
				objNext;

			if ((currentArray.length -1) > currentIndex) {
				href = currentArray[ currentIndex + 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}

			if (currentIndex > 0) {
				href = currentArray[ currentIndex - 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}
		},

		_draw = function(pos) {
			var dim = {
				width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
				height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),

				top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
				left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
			};

			if (typeof final_pos.opacity !== 'undefined') {
				dim.opacity = pos < 0.5 ? 0.5 : pos;
			}

			wrap.css(dim);

			content.css({
				'width' : dim.width - currentOpts.padding * 2,
				'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
			});
		},

		_get_viewport = function() {
			return [
				$(window).width() - (currentOpts.margin * 2),
				$(window).height() - (currentOpts.margin * 2),
				$(document).scrollLeft() + currentOpts.margin,
				$(document).scrollTop() + currentOpts.margin
			];
		},

		_get_zoom_to = function () {
			var view = _get_viewport(),
				to = {},
				resize = currentOpts.autoScale,
				double_padding = currentOpts.padding * 2,
				ratio;

			if (currentOpts.width.toString().indexOf('%') > -1) {
				to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
			} else {
				to.width = currentOpts.width + double_padding;
			}

			if (currentOpts.height.toString().indexOf('%') > -1) {
				to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
			} else {
				to.height = currentOpts.height + double_padding;
			}

			if (resize && (to.width > view[0] || to.height > view[1])) {
				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
					ratio = (currentOpts.width ) / (currentOpts.height );

					if ((to.width ) > view[0]) {
						to.width = view[0];
						to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
					}

					if ((to.height) > view[1]) {
						to.height = view[1];
						to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
					}

				} else {
					to.width = Math.min(to.width, view[0]);
					to.height = Math.min(to.height, view[1]);
				}
			}

			to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
			to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);

			return to;
		},

		_get_obj_pos = function(obj) {
			var pos = obj.offset();

			pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0;
			pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0;

			pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0;
			pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0;

			pos.width = obj.width();
			pos.height = obj.height();

			return pos;
		},

		_get_zoom_from = function() {
			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
				from = {},
				pos,
				view;

			if (orig && orig.length) {
				pos = _get_obj_pos(orig);

				from = {
					width : pos.width + (currentOpts.padding * 2),
					height : pos.height + (currentOpts.padding * 2),
					top	: pos.top - currentOpts.padding - 20,
					left : pos.left - currentOpts.padding - 20
				};

			} else {
				view = _get_viewport();

				from = {
					width : currentOpts.padding * 2,
					height : currentOpts.padding * 2,
					top	: parseInt(view[3] + view[1] * 0.5, 10),
					left : parseInt(view[2] + view[0] * 0.5, 10)
				};
			}

			return from;
		};

	/*
	 * Public methods
	 */

	$.fn.fancybox = function(options) {
		if (!$(this).length) {
			return this;
		}

		$(this)
			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
			.unbind('click.fb')
			.bind('click.fb', function(e) {
				e.preventDefault();

				if (busy) {
					return;
				}

				busy = true;

				$(this).blur();

				selectedArray = [];
				selectedIndex = 0;

				var rel = $(this).attr('rel') || '';

				if (!rel || rel == '' || rel === 'nofollow') {
					selectedArray.push(this);

				} else {
					selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]");
					selectedIndex = selectedArray.index( this );
				}

				_start();

				return;
			});

		return this;
	};

	$.fancybox = function(obj) {
		var opts;

		if (busy) {
			return;
		}

		busy = true;
		opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};

		selectedArray = [];
		selectedIndex = parseInt(opts.index, 10) || 0;

		if ($.isArray(obj)) {
			for (var i = 0, j = obj.length; i < j; i++) {
				if (typeof obj[i] == 'object') {
					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
				} else {
					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
				}
			}

			selectedArray = jQuery.merge(selectedArray, obj);

		} else {
			if (typeof obj == 'object') {
				$(obj).data('fancybox', $.extend({}, opts, obj));
			} else {
				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
			}

			selectedArray.push(obj);
		}

		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
			selectedIndex = 0;
		}

		_start();
	};

	$.fancybox.next = function() {
		return $.fancybox.pos( currentIndex + 1);
	};

	$.fancybox.prev = function() {
		return $.fancybox.pos( currentIndex - 1);
	};

	$.fancybox.pos = function(pos) {
		if (busy) {
			return;
		}

		pos = parseInt(pos);

		selectedArray = currentArray;

		if (pos > -1 && pos < currentArray.length) {
			selectedIndex = pos;
			_start();

		} else if (currentOpts.cyclic && currentArray.length > 1) {
			selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
			_start();
		}

		return;
	};

	$.fancybox.cancel = function() {
		if (busy) {
			return;
		}

		busy = true;

		$.event.trigger('fb-cancel');

		_abort();

		selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);

		busy = false;
	};

	$.fancybox.close = function() {
		if (busy || wrap.is(':hidden')) {
			return;
		}

		busy = true;

		if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
			busy = false;
			return;
		}

		_abort();

		$(nav_left.add(nav_right)).hide();

		$(content.add(overlay)).unbind();

		$(window).unbind("resize.fb scroll.fb");
		$(document).unbind('keydown.fb');

		content.find('iframe').attr('src', 'about:blank');

		wrap.stop();

		function _cleanup() {
			overlay.fadeOut('fast');

			title.empty().hide();
			wrap.hide();

			$.event.trigger('fb-cleanup');

			content.empty();

			currentOpts.onClosed(currentArray, currentIndex, currentOpts);

			currentArray = selectedOpts	= [];
			currentIndex = selectedIndex = 0;
			currentOpts = selectedOpts	= {};

			busy = false;
		}

		if (currentOpts.transitionOut == 'elastic') {
			start_pos = _get_zoom_from();

			var pos = wrap.position();

			final_pos = {
				top	 : pos.top ,
				left : pos.left,
				width :	wrap.width(),
				height : wrap.height()
			};

			if (currentOpts.opacity) {
				final_pos.opacity = 1;
			}

			title.empty().hide();

			fx.prop = 1;

			$(fx).animate({ prop: 0 }, {
				 duration : currentOpts.speedOut,
				 easing : currentOpts.easingOut,
				 step : _draw,
				 complete : _cleanup
			});

		} else {
			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
		}
	};

	$.fancybox.resize = function() {
		if (overlay.is(':visible')) {
			overlay.css('height', $(document).height());
		}

		$.fancybox.center(true);
	};

	$.fancybox.center = function() {
		var view, align;

		if (busy) {
			return;
		}

		align = arguments[0] === true ? 1 : 0;
		view = _get_viewport();

		if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
			return;
		}

		wrap
			.stop()
			.animate({
				'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)),
				'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding))
			}, typeof arguments[0] == 'number' ? arguments[0] : 200);
	};

	$.fancybox.init = function() {
		if ($("#fb-wrap").length) {
			return;
		}

		$('body').append(
			tmp	= $('<div id="fb-tmp"></div>'),
			loading	= $('<div id="fb-loading"></div>'),
			overlay	= $('<div id="fb-overlay"></div>'),
			wrap = $('<div id="fb-wrap"></div>')
		);

		outer = $('<div id="fb-outer"></div>')
			.appendTo( wrap );

		outer.append(
			content = $('<div id="fb-content"></div>'),
			title = $('<div id="fb-title"></div>'),

			nav_left = $('<div id="fb-left"><a>prev</a></<div'),
			nav_right = $('<div id="fb-right"><a>next</a></<div')
		);

		loading.click($.fancybox.cancel);

		$('a', nav_left).click(function(e) {
			e.preventDefault();
			$.fancybox.prev();
		});

		$('a', nav_right).click(function(e) {
			e.preventDefault();
			$.fancybox.next();
		});

		if ($.fn.mousewheel) {
			wrap.bind('mousewheel.fb', function(e, delta) {
				if (busy) {
					e.preventDefault();

				} else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
					e.preventDefault();
					$.fancybox[ delta > 0 ? 'prev' : 'next']();
				}
			});
		}

		if (!$.support.opacity){
			wrap.addClass('fb-ie');
		}

	};

	$.fn.fancybox.defaults = {

		padding : 10,
		margin : 40,
		opacity : false,
		modal : false,
		cyclic : false,
		scrolling : 'auto',	// 'auto', 'yes' or 'no'

		width : 560,
		height : 340,

		autoScale : true,
		autoDimensions : true,
		centerOnScroll : true,

		ajax : {},
		swf : { wmode: 'transparent' },

		hideOnOverlayClick : true,
		hideOnContentClick : false,

		overlayShow : true,
		overlayOpacity : 0.5,

		titleShow : true,
		titleFormat : null,
		titleFromAlt : false,

		transitionIn : 'elastic', // 'elastic', 'fade' or 'none'
		transitionOut : 'elastic', // 'elastic', 'fade' or 'none'

		speedIn : 300,
		speedOut : 300,

		changeSpeed : 300,
		changeFade : 'fast',

		easingIn : 'easeOutBack',
		easingOut : 'easeInBack',

		showNavArrows : true,
		enableEscapeButton : true,
		enableKeyboardNav : true,

		onStart : function(){},
		onCancel : function(){},
		onComplete : function(){},
		onCleanup : function(){},
		onClosed : function(){},
		onError : function(){}
	};

	$(document).ready(function() {
		$.fancybox.init();
	});

})(jQuery);


