/**
 * jQuery lightBox plugin
 * This jQuery plugin was inspired and based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
 * and adapted to me for use like a plugin from jQuery.
 * @name jquery-lightbox-0.4.min.js
 * @author Leandro Vieira Pinho - http://leandrovieira.com
 * @version 0.4
 * @date November 17, 2007
 * @category jQuery plugin
 * @copyright (c) 2007 Leandro Vieira Pinho (leandrovieira.com)
 * @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
 * @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
 */
(function($){$.fn.lightBox=function(settings){settings=jQuery.extend({overlayBgColor:'#000',overlayOpacity:0.8,imageLoading:'images/lightbox-ico-loading.gif',imageBtnPrev:'images/lightbox-btn-prev.gif',imageBtnNext:'images/lightbox-btn-next.gif',imageBtnClose:'images/lightbox-btn-close.gif',imageBlank:'images/lightbox-blank.gif',containerBorderSize:10,containerResizeSpeed:400,txtImage:'Image',txtOf:'of',keyToClose:'c',keyToPrev:'p',keyToNext:'n',imageArray:[],activeImage:0},settings);var jQueryMatchedObj=this;function _initialize(){_start(this,jQueryMatchedObj);return false;}
function _start(objClicked,jQueryMatchedObj){$('embed, object, select').css({'visibility':'hidden'});_set_interface();settings.imageArray.length=0;settings.activeImage=0;if(jQueryMatchedObj.length==1){settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));}else{for(var i=0;i<jQueryMatchedObj.length;i++){settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));}}
while(settings.imageArray[settings.activeImage][0]!=objClicked.getAttribute('href')){settings.activeImage++;}
_set_image_to_view();}
function _set_interface(){$('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="'+settings.imageLoading+'"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="'+settings.imageBtnClose+'"></a></div></div></div></div>');var arrPageSizes=___getPageSize();$('#jquery-overlay').css({backgroundColor:settings.overlayBgColor,opacity:settings.overlayOpacity,width:arrPageSizes[0],height:arrPageSizes[1]}).fadeIn();var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]}).show();$('#jquery-overlay,#jquery-lightbox').click(function(){_finish();});$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function(){_finish();return false;});$(window).resize(function(){var arrPageSizes=___getPageSize();$('#jquery-overlay').css({width:arrPageSizes[0],height:arrPageSizes[1]});var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]});});}
function _set_image_to_view(){$('#lightbox-loading').show();$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();var objImagePreloader=new Image();objImagePreloader.onload=function(){$('#lightbox-image').attr('src',settings.imageArray[settings.activeImage][0]);_resize_container_image_box(objImagePreloader.width,objImagePreloader.height);objImagePreloader.onload=function(){};};objImagePreloader.src=settings.imageArray[settings.activeImage][0];};function _resize_container_image_box(intImageWidth,intImageHeight){var intCurrentWidth=$('#lightbox-container-image-box').width();var intCurrentHeight=$('#lightbox-container-image-box').height();var intWidth=(intImageWidth+(settings.containerBorderSize*2));var intHeight=(intImageHeight+(settings.containerBorderSize*2));var intDiffW=intCurrentWidth-intWidth;var intDiffH=intCurrentHeight-intHeight;$('#lightbox-container-image-box').animate({width:intWidth,height:intHeight},settings.containerResizeSpeed,function(){_show_image();});if((intDiffW==0)&&(intDiffH==0)){if($.browser.msie){___pause(250);}else{___pause(100);}}
$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({height:intImageHeight+(settings.containerBorderSize*2)});$('#lightbox-container-image-data-box').css({width:intImageWidth});};function _show_image(){$('#lightbox-loading').hide();$('#lightbox-image').fadeIn(function(){_show_image_data();_set_navigation();});_preload_neighbor_images();};function _show_image_data(){$('#lightbox-container-image-data-box').slideDown('fast');$('#lightbox-image-details-caption').hide();if(settings.imageArray[settings.activeImage][1]){$('#lightbox-image-details-caption').html(settings.imageArray[settings.activeImage][1]).show();}
if(settings.imageArray.length>1){$('#lightbox-image-details-currentNumber').html(settings.txtImage+' '+(settings.activeImage+1)+' '+settings.txtOf+' '+settings.imageArray.length).show();}}
function _set_navigation(){$('#lightbox-nav').show();$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({'background':'transparent url('+settings.imageBlank+') no-repeat'});if(settings.activeImage!=0){$('#lightbox-nav-btnPrev').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnPrev+') left 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage-1;_set_image_to_view();return false;});}
if(settings.activeImage!=(settings.imageArray.length-1)){$('#lightbox-nav-btnNext').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnNext+') right 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage+1;_set_image_to_view();return false;});}
_enable_keyboard_navigation();}
function _enable_keyboard_navigation(){$(document).keydown(function(objEvent){_keyboard_action(objEvent);});}
function _disable_keyboard_navigation(){$(document).unbind();}
function _keyboard_action(objEvent){if(objEvent==null){keycode=event.keyCode;escapeKey=27;}else{keycode=objEvent.keyCode;escapeKey=objEvent.DOM_VK_ESCAPE;}
key=String.fromCharCode(keycode).toLowerCase();if((key==settings.keyToClose)||(key=='x')||(keycode==escapeKey)){_finish();}
if((key==settings.keyToPrev)||(keycode==37)){if(settings.activeImage!=0){settings.activeImage=settings.activeImage-1;_set_image_to_view();_disable_keyboard_navigation();}}
if((key==settings.keyToNext)||(keycode==39)){if(settings.activeImage!=(settings.imageArray.length-1)){settings.activeImage=settings.activeImage+1;_set_image_to_view();_disable_keyboard_navigation();}}}
function _preload_neighbor_images(){if((settings.imageArray.length-1)>settings.activeImage){objNext=new Image();objNext.src=settings.imageArray[settings.activeImage+1][0];}
if(settings.activeImage>0){objPrev=new Image();objPrev.src=settings.imageArray[settings.activeImage-1][0];}}
function _finish(){$('#jquery-lightbox').remove();$('#jquery-overlay').fadeOut(function(){$('#jquery-overlay').remove();});$('embed, object, select').css({'visibility':'visible'});}
function ___getPageSize(){var xScroll,yScroll;if(window.innerHeight&&window.scrollMaxY){xScroll=window.innerWidth+window.scrollMaxX;yScroll=window.innerHeight+window.scrollMaxY;}else if(document.body.scrollHeight>document.body.offsetHeight){xScroll=document.body.scrollWidth;yScroll=document.body.scrollHeight;}else{xScroll=document.body.offsetWidth;yScroll=document.body.offsetHeight;}
var windowWidth,windowHeight;if(self.innerHeight){if(document.documentElement.clientWidth){windowWidth=document.documentElement.clientWidth;}else{windowWidth=self.innerWidth;}
windowHeight=self.innerHeight;}else if(document.documentElement&&document.documentElement.clientHeight){windowWidth=document.documentElement.clientWidth;windowHeight=document.documentElement.clientHeight;}else if(document.body){windowWidth=document.body.clientWidth;windowHeight=document.body.clientHeight;}
if(yScroll<windowHeight){pageHeight=windowHeight;}else{pageHeight=yScroll;}
if(xScroll<windowWidth){pageWidth=xScroll;}else{pageWidth=windowWidth;}
arrayPageSize=new Array(pageWidth,pageHeight,windowWidth,windowHeight);return arrayPageSize;};function ___getPageScroll(){var xScroll,yScroll;if(self.pageYOffset){yScroll=self.pageYOffset;xScroll=self.pageXOffset;}else if(document.documentElement&&document.documentElement.scrollTop){yScroll=document.documentElement.scrollTop;xScroll=document.documentElement.scrollLeft;}else if(document.body){yScroll=document.body.scrollTop;xScroll=document.body.scrollLeft;}
arrayPageScroll=new Array(xScroll,yScroll);return arrayPageScroll;};function ___pause(ms){var date=new Date();curDate=null;do{var curDate=new Date();}
while(curDate-date<ms);};return this.unbind('click').click(_initialize);};})(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
 */

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.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);
			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)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);


/********************* BOXY *********************/

//Boxy - Facebook-style dialog, with frills
//(c) 2008 Jason Frame

//TODO: multi-select list
//TODO: allow resizing when not visible
//BUG: modal dialog blackout doesn't resize when window resizes
//BUG: 'single' option to main plugin method not yet supported.

//
//jQuery Plugin

//single - only show a single instance at a time (default: true)
//cache - if true, data retrieved from AJAX calls will be cached. Inline data
//      will always be cached as we need to stash it someplace outside the DOM
//      to avoid having multiple elements with the same ID.
//message - confirmation message for form submit hook (default: "Please confirm:")
//method - AJAX method to use for loading remote content (default: GET)
//(any leftover options - e.g. 'clone' - will be passed onto the boxy constructor)
$.fn.boxy = function(options) {
 options = $.extend({single: true}, options || {});
 this.each(function() {      
     var node = this.nodeName.toLowerCase(), self = this;
     if (node == 'a') {
         $(this).click(function() {
             var anchor = this,
                 href = this.getAttribute('href'),
                 realOpts = $.extend(options, {title: this.title});
                 
             var loadContent = function(after) {
                 if (Boxy.cache[href]) {
                     after(Boxy.cache[href].clone());   
                 } else if (href.indexOf('#') === 0) {
                     Boxy.cache[href] = $(href).remove();
                     after(Boxy.cache[href].clone());
                 } else { // fall back to AJAX; could do with a same-origin check
                     $.ajax({
                         url: anchor.href,
                         method: options.method || 'GET',
                         dataType: 'html',
                         success: function(data) {
                             data = $(data);
                             if (options.cache) {
                                 Boxy.cache[href] = data;
                                 data = data.clone();
                             }
                             after(data);
                         }
                     });
                 }
             };
             
             var active;
             if (options.single && (active = $.data(this, 'active.boxy'))) {
                 loadContent(function(content) {
                     active.setContent(content).center().show();     
                 });
             } else {
                 loadContent(function(content) {
                     $.data(anchor, 'active.boxy', new Boxy(content, realOpts));     
                 });
             }
             
             return false;
         });
     } else if (node == 'form') {
         $(this).bind('submit.boxy', function() {
             Boxy.ask(options.message || 'Please confirm:', ['OK', 'Cancel'], function(v) {
                 if (v == 'OK') {
                     $(self).unbind('submit.boxy').submit();
                 }
             }, {modal: true, closeable: false});
             return false;
         });
     }
 });
};

//
//Boxy Class

function Boxy(element, options) {
 
 this.boxy = $(this.WRAPPER);
 $.data(this.boxy[0], 'boxy', this);
 
 this.visible = false;
 this.options = $.extend({
     title: null, closeable: true, draggable: true, clone: false,
     center: true, show: true, modal: false
 }, options || {});
 
 if (this.options.modal) {
     this.options = $.extend(this.options, {center: true, draggable: false});
 }
 
 this.setContent(element || "<div></div>");
 this._setupTitleBar();
 this._setupBehaviours();
 
 this.boxy.css('display', 'none').appendTo(document.body);
 this.toTop();
 
 if (this.options.center
     && typeof this.options.x == 'undefined'
     && typeof this.options.y == 'undefined') {
     this.center();
 } else {
     this.moveTo(this.options.x || Boxy.DEFAULT_X,
                 this.options.y || Boxy.DEFAULT_Y);
 }
 
 if (this.options.show) this.show();

};

$.extend(Boxy, {
 DEFAULT_X:          50,
 DEFAULT_Y:          50,
 cache:              {},
 zIndex:             1337,
 dragConfigured:     false, // only set up one drag handler for all boxys
 dragging:           null,
 
 // allows you to get a handle to the containing boxy instance of any element
 // e.g. <a href='#' onclick='alert(Boxy.get(this));'>inspect!</a>.
 // this returns the actual instance of the boxy 'class', not just a DOM element.
 // Boxy.get(this).hide() would be valid, for instance.
 get: function(ele) {
     var p = $(ele).parents('.boxy-wrapper');
     return p.length ? $.data(p[0], 'boxy') : null;
 },
 
 // asks a question with multiple responses presented as buttons
 // selected item is returned to a callback method.
 // answers may be either an array or a hash. if it's an array, the
 // the callback will received the selected value. if it's a hash,
 // you'll get the corresponding key.
 ask: function(question, answers, callback, options) {
     
     options = $.extend({modal: true, closeable: false}, options, {show: true});
     
     var body = $('<div></div>').append($('<div class="question"></div>').html(question));
     
     // ick
     var map = {}, answerStrings = [];
     if (answers instanceof Array) {
         for (var i = 0; i < answers.length; i++) {
             map[answers[i]] = answers[i];
             answerStrings.push(answers[i]);
         }
     } else {
         for (var k in answers) {
             map[answers[k]] = k;
             answerStrings.push(answers[k]);
         }
     }
     
     var buttons = $('<form class="answers"></form>');
     buttons.html($.map(answerStrings, function(v) {
         return "<input type='button' value='" + v + "' />";
     }).join(' '));
     
     $('input[type=button]', buttons).click(function() {
         var clicked = this;
         Boxy.get(this).hide(function() {
             if (callback) callback(map[clicked.value]);
         });
     });
     
     body.append(buttons);
     
     new Boxy(body, options);
     
 },
 
 _handleDrag: function(evt) {
     var d;
     if (d = Boxy.dragging) {
         d[0].boxy.css({left: evt.pageX - d[1], top: evt.pageY - d[2]});
     }
 },
 
 _nextZ: function() {
     return Boxy.zIndex++;
 }
});

Boxy.prototype = {
 
 WRAPPER:    "<table cellspacing='0' cellpadding='0' border='0' class='boxy-wrapper'>" +
                 "<tr><td class='top-left'></td><td class='top'></td><td class='top-right'></td></tr>" +
                 "<tr><td class='left'></td><td class='boxy-inner'></td><td class='right'></td></tr>" +
                 "<tr><td class='bottom-left'></td><td class='top'></td><td class='bottom-right'></td></tr>" +
             "</table>",
 
 // Returns the size of this boxy instance without displaying it.
 // Do not use this method if boxy is already visible, use getSize() instead.
 estimateSize: function() {
     this.boxy.css('display', 'none')
              .css({top: 0, left: 0, visibility: 'hidden'})
              .css('display', 'block');
     var dims = this.getSize();
     this.boxy.css('display', 'none').css('visibility', 'visible');
     return dims;
 },
             
 // Returns the dimensions of the entire boxy dialog as [width,height]
 getSize: function() {
     return [this.boxy.width(), this.boxy.height()];
 },
 
 // Returns the dimensions of the content region as [width,height]
 getContentSize: function() {
     var c = this.getContent();
     return [c.width(), c.height()];
 },
 
 // Returns the position of this dialog as [x,y]
 getPosition: function() {
     var b = this.boxy[0];
     return [b.offsetLeft, b.offsetTop];
 },
 
 // Returns the center point of this dialog as [x,y]
 getCenter: function() {
     var p = this.getPosition();
     var s = this.getSize();
     return [Math.floor(p[0] + s[0] / 2), Math.floor(p[1] + s[1] / 2)];
 },
             
 // Returns a jQuery object wrapping the inner boxy region.
 // Not much reason to use this, you're probably more interested in getContent()
 getInner: function() {
     return $('.boxy-inner', this.boxy);
 },
 
 // Returns a jQuery object wrapping the boxy content region.
 // This is the user-editable content area (i.e. excludes titlebar)
 getContent: function() {
     return $('.boxy-content', this.boxy);
 },
 
 // Replace dialog content
 setContent: function(newContent) {
     newContent = $(newContent).css({display: 'block'}).addClass('boxy-content');
     if (this.options.clone) newContent = newContent.clone();   
     var content = this.getContent();
     if (content.length) {
         content.replaceWith(newContent);   
     } else {
         this.getInner().append(newContent);
     }
     return this;
 },
 
 // Move this dialog to some position, funnily enough
 moveTo: function(x, y) {
     this.boxy.css({left: x, top: y});
     return this;
 },
 
 // Move this dialog so that it is centered at x,y
 centerAt: function(x, y) {
     if (this.visible) {
         var s = this.getSize();
     } else {
         var s = this.estimateSize();
     }
     this.moveTo(x - s[0] / 2, y - s[1] / 2);
     return this;
 },
 
 // Center this dialog in the viewport
 center: function() {
     var s = $.browser.msie ? [document.body.scrollLeft, document.body.scrollTop]
                            : [window.pageXOffset, window.pageYOffset];
     var v = [s[0], s[1], $(window).width(), $(window).height()];
     this.centerAt((v[0] + v[2] / 2), (v[1] + v[3] / 2));
     return this;
 },
 
 // Resize the content region to a specific size
 resize: function(width, height, after) {
     if (!this.visible) return;
     var bounds = this._getBoundsForResize(width, height);
     this.boxy.css({left: bounds[0], top: bounds[1]});
     this.getContent().css({width: bounds[2], height: bounds[3]});
     if (after) after(this);
     return this;
 },
 
 // Tween the content region to a specific size
 tween: function(width, height, after) {
     if (!this.visible) return;
     var bounds = this._getBoundsForResize(width, height);
     var self = this;
     this.boxy.stop().animate({left: bounds[0], top: bounds[1]});
     this.getContent().stop().animate({width: bounds[2], height: bounds[3]}, function() {
         if (after) after(self);
     });
     return this;
 },
 
 isVisible: function() {
     return this.visible;    
 },
 
 // Make this boxy instance visible
 show: function() {
     if (this.visible) return;
     if (this.options.modal) {
         $('<div class="boxy-modal-blackout"></div>')
             .css({zIndex: Boxy._nextZ(),
                   width: $(document).width(),
                   height: $(document).height()})
             .appendTo(document.body);
         this.toTop();
     }
     this.boxy.stop().css({opacity: 1, display: 'block'});
     this.visible = true;
     return this;
 },
 
 // Hide this boxy instance
 hide: function(after) {
     if (!this.visible) return;
     var self = this;
     if (this.options.modal) {
         $('.boxy-modal-blackout').animate({opacity: 0}, function() {
             $(this).remove();
         });
     }
     this.boxy.stop().animate({opacity: 0}, 300, function() {
         self.boxy.css({display: 'none'});
         self.visible = false;
         if (after) after(self);
     });
     return this;
 },
 
 // Move this dialog box above all other boxy instances
 toTop: function() {
     this.boxy.css({zIndex: Boxy._nextZ()});
     return this;
 },
 
 //
 // Don't touch these privates
 
 _getBoundsForResize: function(width, height) {
     var csize = this.getContentSize();
     var delta = [width - csize[0], height - csize[1]];
     var p = this.getPosition();
     return [Math.max(p[0] - delta[0] / 2, 0),
             Math.max(p[1] - delta[1] / 2, 0), width, height];
 },
 
 _setupTitleBar: function() {
     if (this.options.title) {
         var self = this;
         var tb = $("<div class='title-bar'></div>").html(this.options.title);
         if (this.options.closeable) {
             tb.append($("<a href='#' class='close'></a>").html("[close]"));
         }
         if (this.options.draggable) {
             if (!Boxy.dragConfigured) {
                 $(document).mousemove(Boxy._handleDrag);
                 Boxy.dragConfigured = true;
             }
             tb.mousedown(function(evt) {
                 self.toTop();
                 Boxy.dragging = [self, evt.pageX - self.boxy[0].offsetLeft, evt.pageY - self.boxy[0].offsetTop];
                 $(this).addClass('dragging');
             });
             tb.mouseup(function() {
                 $(this).removeClass('dragging');
                 Boxy.dragging = null;
             });
         }
         this.getInner().prepend(tb);
     }
 },
 
 _setupBehaviours: function() {
     var self = this;
     $('.close', this.boxy).click(function() {
         self.hide();
         return false;
     }).mousedown(function(evt) { evt.stopPropagation(); });
 }
 
};
