
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console) {
    arguments.callee = arguments.callee.caller;
    var newarr = [].slice.call(arguments);
    (typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
  }
};

// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
{console.log();return window.console;}catch(err){return window.console={};}})());


// place any jQuery/helper plugins in here, instead of separate, slower script files.
/*
 * jQuery Nivo Slider v2.6
 * http://nivo.dev7studios.com
 *
 * Copyright 2011, Gilbert Pellegrom
 * Free to use and abuse under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * March 2010
 */

(function($){var NivoSlider=function(element,options){var settings=$.extend({},$.fn.nivoSlider.defaults,options);var vars={currentSlide:0,currentImage:'',totalSlides:0,randAnim:'',running:false,paused:false,stop:false};var slider=$(element);slider.data('nivo:vars',vars);slider.css('position','relative');slider.addClass('nivoSlider');var kids=slider.children();kids.each(function(){var child=$(this);var link='';if(!child.is('img')){if(child.is('a')){child.addClass('nivo-imageLink');link=child;}
child=child.find('img:first');}
var childWidth=child.width();if(childWidth==0)childWidth=child.attr('width');var childHeight=child.height();if(childHeight==0)childHeight=child.attr('height');if(childWidth>slider.width()){slider.width(childWidth);}
if(childHeight>slider.height()){slider.height(childHeight);}
if(link!=''){link.css('display','none');}
child.css('display','none');vars.totalSlides++;});if(settings.startSlide>0){if(settings.startSlide>=vars.totalSlides)settings.startSlide=vars.totalSlides-1;vars.currentSlide=settings.startSlide;}
if($(kids[vars.currentSlide]).is('img')){vars.currentImage=$(kids[vars.currentSlide]);}else{vars.currentImage=$(kids[vars.currentSlide]).find('img:first');}
if($(kids[vars.currentSlide]).is('a')){$(kids[vars.currentSlide]).css('display','block');}
slider.css('background','url("'+vars.currentImage.attr('src')+'") no-repeat');slider.append($('<div class="nivo-caption"><p></p></div>').css({display:'none',opacity:settings.captionOpacity}));var processCaption=function(settings){var nivoCaption=$('.nivo-caption',slider);if(vars.currentImage.attr('title')!=''&&vars.currentImage.attr('title')!=undefined){var title=vars.currentImage.attr('title');if(title.substr(0,1)=='#')title=$(title).html();if(nivoCaption.css('display')=='block'){nivoCaption.find('p').fadeOut(settings.animSpeed,function(){$(this).html(title);$(this).fadeIn(settings.animSpeed);});}else{nivoCaption.find('p').html(title);}
nivoCaption.fadeIn(settings.animSpeed);}else{nivoCaption.fadeOut(settings.animSpeed);}}
processCaption(settings);var timer=0;if(!settings.manualAdvance&&kids.length>1){timer=setInterval(function(){nivoRun(slider,kids,settings,false);},settings.pauseTime);}
if(settings.directionNav){slider.append('<div class="nivo-directionNav"><a class="nivo-prevNav">'+settings.prevText+'</a><a class="nivo-nextNav">'+settings.nextText+'</a></div>');if(settings.directionNavHide){$('.nivo-directionNav',slider).hide();slider.hover(function(){$('.nivo-directionNav',slider).show();},function(){$('.nivo-directionNav',slider).hide();});}
$('a.nivo-prevNav',slider).live('click',function(){if(vars.running)return false;clearInterval(timer);timer='';vars.currentSlide-=2;nivoRun(slider,kids,settings,'prev');});$('a.nivo-nextNav',slider).live('click',function(){if(vars.running)return false;clearInterval(timer);timer='';nivoRun(slider,kids,settings,'next');});}
if(settings.controlNav){var nivoControl=$('<div class="nivo-controlNav"></div>');slider.append(nivoControl);for(var i=0;i<kids.length;i++){if(settings.controlNavThumbs){var child=kids.eq(i);if(!child.is('img')){child=child.find('img:first');}
if(settings.controlNavThumbsFromRel){nivoControl.append('<a class="nivo-control" rel="'+i+'"><img src="'+child.attr('rel')+'" alt="" /></a>');}else{nivoControl.append('<a class="nivo-control" rel="'+i+'"><img src="'+child.attr('src').replace(settings.controlNavThumbsSearch,settings.controlNavThumbsReplace)+'" alt="" /></a>');}}else{nivoControl.append('<a class="nivo-control" rel="'+i+'">'+(i+1)+'</a>');}}
$('.nivo-controlNav a:eq('+vars.currentSlide+')',slider).addClass('active');$('.nivo-controlNav a',slider).live('click',function(){if(vars.running)return false;if($(this).hasClass('active'))return false;clearInterval(timer);timer='';slider.css('background','url("'+vars.currentImage.attr('src')+'") no-repeat');vars.currentSlide=$(this).attr('rel')-1;nivoRun(slider,kids,settings,'control');});}
if(settings.keyboardNav){$(window).keypress(function(event){if(event.keyCode=='37'){if(vars.running)return false;clearInterval(timer);timer='';vars.currentSlide-=2;nivoRun(slider,kids,settings,'prev');}
if(event.keyCode=='39'){if(vars.running)return false;clearInterval(timer);timer='';nivoRun(slider,kids,settings,'next');}});}
if(settings.pauseOnHover){slider.hover(function(){vars.paused=true;clearInterval(timer);timer='';},function(){vars.paused=false;if(timer==''&&!settings.manualAdvance){timer=setInterval(function(){nivoRun(slider,kids,settings,false);},settings.pauseTime);}});}
slider.bind('nivo:animFinished',function(){vars.running=false;$(kids).each(function(){if($(this).is('a')){$(this).css('display','none');}});if($(kids[vars.currentSlide]).is('a')){$(kids[vars.currentSlide]).css('display','block');}
if(timer==''&&!vars.paused&&!settings.manualAdvance){timer=setInterval(function(){nivoRun(slider,kids,settings,false);},settings.pauseTime);}
settings.afterChange.call(this);});var createSlices=function(slider,settings,vars){for(var i=0;i<settings.slices;i++){var sliceWidth=Math.round(slider.width()/settings.slices);if(i==settings.slices-1){slider.append($('<div class="nivo-slice"></div>').css({left:(sliceWidth*i)+'px',width:(slider.width()-(sliceWidth*i))+'px',height:'0px',opacity:'0',background:'url("'+vars.currentImage.attr('src')+'") no-repeat -'+((sliceWidth+(i*sliceWidth))-sliceWidth)+'px 0%'}));}else{slider.append($('<div class="nivo-slice"></div>').css({left:(sliceWidth*i)+'px',width:sliceWidth+'px',height:'0px',opacity:'0',background:'url("'+vars.currentImage.attr('src')+'") no-repeat -'+((sliceWidth+(i*sliceWidth))-sliceWidth)+'px 0%'}));}}}
var createBoxes=function(slider,settings,vars){var boxWidth=Math.round(slider.width()/settings.boxCols);var boxHeight=Math.round(slider.height()/settings.boxRows);for(var rows=0;rows<settings.boxRows;rows++){for(var cols=0;cols<settings.boxCols;cols++){if(cols==settings.boxCols-1){slider.append($('<div class="nivo-box"></div>').css({opacity:0,left:(boxWidth*cols)+'px',top:(boxHeight*rows)+'px',width:(slider.width()-(boxWidth*cols))+'px',height:boxHeight+'px',background:'url("'+vars.currentImage.attr('src')+'") no-repeat -'+((boxWidth+(cols*boxWidth))-boxWidth)+'px -'+((boxHeight+(rows*boxHeight))-boxHeight)+'px'}));}else{slider.append($('<div class="nivo-box"></div>').css({opacity:0,left:(boxWidth*cols)+'px',top:(boxHeight*rows)+'px',width:boxWidth+'px',height:boxHeight+'px',background:'url("'+vars.currentImage.attr('src')+'") no-repeat -'+((boxWidth+(cols*boxWidth))-boxWidth)+'px -'+((boxHeight+(rows*boxHeight))-boxHeight)+'px'}));}}}}
var nivoRun=function(slider,kids,settings,nudge){var vars=slider.data('nivo:vars');if(vars&&(vars.currentSlide==vars.totalSlides-1)){settings.lastSlide.call(this);}
if((!vars||vars.stop)&&!nudge)return false;settings.beforeChange.call(this);if(!nudge){slider.css('background','url("'+vars.currentImage.attr('src')+'") no-repeat');}else{if(nudge=='prev'){slider.css('background','url("'+vars.currentImage.attr('src')+'") no-repeat');}
if(nudge=='next'){slider.css('background','url("'+vars.currentImage.attr('src')+'") no-repeat');}}
vars.currentSlide++;if(vars.currentSlide==vars.totalSlides){vars.currentSlide=0;settings.slideshowEnd.call(this);}
if(vars.currentSlide<0)vars.currentSlide=(vars.totalSlides-1);if($(kids[vars.currentSlide]).is('img')){vars.currentImage=$(kids[vars.currentSlide]);}else{vars.currentImage=$(kids[vars.currentSlide]).find('img:first');}
if(settings.controlNav){$('.nivo-controlNav a',slider).removeClass('active');$('.nivo-controlNav a:eq('+vars.currentSlide+')',slider).addClass('active');}
processCaption(settings);$('.nivo-slice',slider).remove();$('.nivo-box',slider).remove();if(settings.effect=='random'){var anims=new Array('sliceDownRight','sliceDownLeft','sliceUpRight','sliceUpLeft','sliceUpDown','sliceUpDownLeft','fold','fade','boxRandom','boxRain','boxRainReverse','boxRainGrow','boxRainGrowReverse');vars.randAnim=anims[Math.floor(Math.random()*(anims.length+1))];if(vars.randAnim==undefined)vars.randAnim='fade';}
if(settings.effect.indexOf(',')!=-1){var anims=settings.effect.split(',');vars.randAnim=anims[Math.floor(Math.random()*(anims.length))];if(vars.randAnim==undefined)vars.randAnim='fade';}
vars.running=true;if(settings.effect=='sliceDown'||settings.effect=='sliceDownRight'||vars.randAnim=='sliceDownRight'||settings.effect=='sliceDownLeft'||vars.randAnim=='sliceDownLeft'){createSlices(slider,settings,vars);var timeBuff=0;var i=0;var slices=$('.nivo-slice',slider);if(settings.effect=='sliceDownLeft'||vars.randAnim=='sliceDownLeft')slices=$('.nivo-slice',slider)._reverse();slices.each(function(){var slice=$(this);slice.css({'top':'0px'});if(i==settings.slices-1){setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed,'',function(){slider.trigger('nivo:animFinished');});},(100+timeBuff));}else{setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed);},(100+timeBuff));}
timeBuff+=50;i++;});}
else if(settings.effect=='sliceUp'||settings.effect=='sliceUpRight'||vars.randAnim=='sliceUpRight'||settings.effect=='sliceUpLeft'||vars.randAnim=='sliceUpLeft'){createSlices(slider,settings,vars);var timeBuff=0;var i=0;var slices=$('.nivo-slice',slider);if(settings.effect=='sliceUpLeft'||vars.randAnim=='sliceUpLeft')slices=$('.nivo-slice',slider)._reverse();slices.each(function(){var slice=$(this);slice.css({'bottom':'0px'});if(i==settings.slices-1){setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed,'',function(){slider.trigger('nivo:animFinished');});},(100+timeBuff));}else{setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed);},(100+timeBuff));}
timeBuff+=50;i++;});}
else if(settings.effect=='sliceUpDown'||settings.effect=='sliceUpDownRight'||vars.randAnim=='sliceUpDown'||settings.effect=='sliceUpDownLeft'||vars.randAnim=='sliceUpDownLeft'){createSlices(slider,settings,vars);var timeBuff=0;var i=0;var v=0;var slices=$('.nivo-slice',slider);if(settings.effect=='sliceUpDownLeft'||vars.randAnim=='sliceUpDownLeft')slices=$('.nivo-slice',slider)._reverse();slices.each(function(){var slice=$(this);if(i==0){slice.css('top','0px');i++;}else{slice.css('bottom','0px');i=0;}
if(v==settings.slices-1){setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed,'',function(){slider.trigger('nivo:animFinished');});},(100+timeBuff));}else{setTimeout(function(){slice.animate({height:'100%',opacity:'1.0'},settings.animSpeed);},(100+timeBuff));}
timeBuff+=50;v++;});}
else if(settings.effect=='fold'||vars.randAnim=='fold'){createSlices(slider,settings,vars);var timeBuff=0;var i=0;$('.nivo-slice',slider).each(function(){var slice=$(this);var origWidth=slice.width();slice.css({top:'0px',height:'100%',width:'0px'});if(i==settings.slices-1){setTimeout(function(){slice.animate({width:origWidth,opacity:'1.0'},settings.animSpeed,'',function(){slider.trigger('nivo:animFinished');});},(100+timeBuff));}else{setTimeout(function(){slice.animate({width:origWidth,opacity:'1.0'},settings.animSpeed);},(100+timeBuff));}
timeBuff+=50;i++;});}
else if(settings.effect=='fade'||vars.randAnim=='fade'){createSlices(slider,settings,vars);var firstSlice=$('.nivo-slice:first',slider);firstSlice.css({'height':'100%','width':slider.width()+'px'});firstSlice.animate({opacity:'1.0'},(settings.animSpeed*2),'',function(){slider.trigger('nivo:animFinished');});}
else if(settings.effect=='slideInRight'||vars.randAnim=='slideInRight'){createSlices(slider,settings,vars);var firstSlice=$('.nivo-slice:first',slider);firstSlice.css({'height':'100%','width':'0px','opacity':'1'});firstSlice.animate({width:slider.width()+'px'},(settings.animSpeed*2),'',function(){slider.trigger('nivo:animFinished');});}
else if(settings.effect=='slideInLeft'||vars.randAnim=='slideInLeft'){createSlices(slider,settings,vars);var firstSlice=$('.nivo-slice:first',slider);firstSlice.css({'height':'100%','width':'0px','opacity':'1','left':'','right':'0px'});firstSlice.animate({width:slider.width()+'px'},(settings.animSpeed*2),'',function(){firstSlice.css({'left':'0px','right':''});slider.trigger('nivo:animFinished');});}
else if(settings.effect=='boxRandom'||vars.randAnim=='boxRandom'){createBoxes(slider,settings,vars);var totalBoxes=settings.boxCols*settings.boxRows;var i=0;var timeBuff=0;var boxes=shuffle($('.nivo-box',slider));boxes.each(function(){var box=$(this);if(i==totalBoxes-1){setTimeout(function(){box.animate({opacity:'1'},settings.animSpeed,'',function(){slider.trigger('nivo:animFinished');});},(100+timeBuff));}else{setTimeout(function(){box.animate({opacity:'1'},settings.animSpeed);},(100+timeBuff));}
timeBuff+=20;i++;});}
else if(settings.effect=='boxRain'||vars.randAnim=='boxRain'||settings.effect=='boxRainReverse'||vars.randAnim=='boxRainReverse'||settings.effect=='boxRainGrow'||vars.randAnim=='boxRainGrow'||settings.effect=='boxRainGrowReverse'||vars.randAnim=='boxRainGrowReverse'){createBoxes(slider,settings,vars);var totalBoxes=settings.boxCols*settings.boxRows;var i=0;var timeBuff=0;var rowIndex=0;var colIndex=0;var box2Darr=new Array();box2Darr[rowIndex]=new Array();var boxes=$('.nivo-box',slider);if(settings.effect=='boxRainReverse'||vars.randAnim=='boxRainReverse'||settings.effect=='boxRainGrowReverse'||vars.randAnim=='boxRainGrowReverse'){boxes=$('.nivo-box',slider)._reverse();}
boxes.each(function(){box2Darr[rowIndex][colIndex]=$(this);colIndex++;if(colIndex==settings.boxCols){rowIndex++;colIndex=0;box2Darr[rowIndex]=new Array();}});for(var cols=0;cols<(settings.boxCols*2);cols++){var prevCol=cols;for(var rows=0;rows<settings.boxRows;rows++){if(prevCol>=0&&prevCol<settings.boxCols){(function(row,col,time,i,totalBoxes){var box=$(box2Darr[row][col]);var w=box.width();var h=box.height();if(settings.effect=='boxRainGrow'||vars.randAnim=='boxRainGrow'||settings.effect=='boxRainGrowReverse'||vars.randAnim=='boxRainGrowReverse'){box.width(0).height(0);}
if(i==totalBoxes-1){setTimeout(function(){box.animate({opacity:'1',width:w,height:h},settings.animSpeed/1.3,'',function(){slider.trigger('nivo:animFinished');});},(100+time));}else{setTimeout(function(){box.animate({opacity:'1',width:w,height:h},settings.animSpeed/1.3);},(100+time));}})(rows,prevCol,timeBuff,i,totalBoxes);i++;}
prevCol--;}
timeBuff+=100;}}}
var shuffle=function(arr){for(var j,x,i=arr.length;i;j=parseInt(Math.random()*i),x=arr[--i],arr[i]=arr[j],arr[j]=x);return arr;}
var trace=function(msg){if(this.console&&typeof console.log!="undefined")
console.log(msg);}
this.stop=function(){if(!$(element).data('nivo:vars').stop){$(element).data('nivo:vars').stop=true;trace('Stop Slider');}}
this.start=function(){if($(element).data('nivo:vars').stop){$(element).data('nivo:vars').stop=false;trace('Start Slider');}}
settings.afterLoad.call(this);return this;};$.fn.nivoSlider=function(options){return this.each(function(key,value){var element=$(this);if(element.data('nivoslider'))return element.data('nivoslider');var nivoslider=new NivoSlider(this,options);element.data('nivoslider',nivoslider);});};$.fn.nivoSlider.defaults={effect:'random',slices:15,boxCols:8,boxRows:4,animSpeed:500,pauseTime:3000,startSlide:0,directionNav:true,directionNavHide:true,controlNav:true,controlNavThumbs:false,controlNavThumbsFromRel:false,controlNavThumbsSearch:'.jpg',controlNavThumbsReplace:'_thumb.jpg',keyboardNav:true,pauseOnHover:true,manualAdvance:false,captionOpacity:0.8,prevText:'Prev',nextText:'Next',beforeChange:function(){},afterChange:function(){},slideshowEnd:function(){},lastSlide:function(){},afterLoad:function(){}};$.fn._reverse=[].reverse;})(jQuery);


/*
 tiny carousel
 */

(function($){$.tiny=$.tiny||{};$.tiny.carousel={options:{start:1,display:1,axis:'x',controls:true,pager:false,interval:false,intervaltime:3000,rewind:false,animation:true,duration:1000,callback:null}};$.fn.tinycarousel=function(options){var options=$.extend({},$.tiny.carousel.options,options);this.each(function(){$(this).data('tcl',new Carousel($(this),options));});return this;};$.fn.tinycarousel_start=function(){$(this).data('tcl').start();};$.fn.tinycarousel_stop=function(){$(this).data('tcl').stop();};$.fn.tinycarousel_move=function(iNum){$(this).data('tcl').move(iNum-1,true);};function Carousel(root,options){var oSelf=this;var oViewport=$('.viewport:first',root);var oContent=$('.overview:first',root);var oPages=oContent.children();var oBtnNext=$('.next:first',root);var oBtnPrev=$('.prev:first',root);var oPager=$('.pager:first',root);var iPageSize,iSteps,iCurrent,oTimer,bPause,bForward=true,bAxis=options.axis=='x';
function initialize(){iPageSize=bAxis?$(oPages[0]).outerWidth(true):$(oPages[0]).outerHeight(true);var iLeftover=Math.ceil(((bAxis?oViewport.outerWidth():oViewport.outerHeight())/(iPageSize*options.display))-1);iSteps=Math.max(1,Math.ceil(oPages.length/options.display)-iLeftover);iCurrent=Math.min(iSteps,Math.max(1,options.start))-2;oContent.css(bAxis?'width':'height',(iPageSize*oPages.length));oSelf.move(1);setEvents();}
function setEvents(){if(options.controls&&oBtnPrev.length>0&&oBtnNext.length>0){oBtnPrev.click(function(){oSelf.move(-1);return false;});oBtnNext.click(function(){oSelf.move(1);return false;});}if(options.interval){root.hover(oSelf.stop,oSelf.start);}if(options.pager&&oPager.length>0){$('a',oPager).click(setPager);}};
function setButtons(){if(options.controls){oBtnPrev.toggleClass('disable',!(iCurrent>0));oBtnNext.toggleClass('disable',!(iCurrent+1<iSteps));}if(options.pager){var oNumbers=$('.pagenum',oPager);oNumbers.removeClass('active');$(oNumbers[iCurrent]).addClass('active');}};
function setPager(oEvent){if($(this).hasClass('pagenum')){oSelf.move(parseInt(this.rel),true);}return false;};
function setTimer(){if(options.interval&&!bPause){clearTimeout(oTimer);oTimer=setTimeout(function(){iCurrent=iCurrent+1==iSteps?-1:iCurrent;bForward=iCurrent+1==iSteps?false:iCurrent==0?true:bForward;oSelf.move(bForward?1:-1);},options.intervaltime);}};
this.stop=function(){clearTimeout(oTimer);bPause=true;};
this.start=function(){bPause=false;setTimer();};
this.move=function(iDirection,bPublic){iCurrent=bPublic?iDirection:iCurrent+=iDirection;if(iCurrent>-1&&iCurrent<iSteps){var oPosition={};oPosition[bAxis?'left':'top']=-(iCurrent*(iPageSize*options.display));oContent.animate(oPosition,{queue:false,duration:options.animation?options.duration:0,complete:function(){if(typeof options.callback=='function')options.callback.call(this,oPages[iCurrent],iCurrent);}});setButtons();setTimer();}};return initialize();};})(jQuery);


/*
 * nyroModal - jQuery Plugin
 * http://nyromodal.nyrodev.com
 *
 * Copyright (c) 2010 Cedric Nirousset (nyrodev.com)
 * Licensed under the MIT license
 *
 * $Date: 2010-02-23 (Tue, 23 Feb 2010) $
 * $version: 1.6.2
 */
jQuery(function($) {

	// -------------------------------------------------------
	// Private Variables
	// -------------------------------------------------------

	var userAgent = navigator.userAgent.toLowerCase();
	var browserVersion = (userAgent.match(/.+(?:rv|webkit|khtml|opera|msie)[\/: ]([\d.]+)/ ) || [0,'0'])[1];

	var isIE6 = (/msie/.test(userAgent) && !/opera/.test(userAgent) && parseInt(browserVersion) < 7 && (!window.XMLHttpRequest || typeof(XMLHttpRequest) === 'function'));
	var body = $('body');

	var currentSettings;
	var callingSettings;

	var shouldResize = false;

	var gallery = {};

	// To know if the fix for the Issue 10 should be applied (or has been applied)
	var fixFF = false;

	// Used for retrieve the content from an hidden div
	var contentElt;
	var contentEltLast;

	// Contains info about nyroModal state and all div references
	var modal = {
		started: false,
		ready: false,
		dataReady: false,
		anim: false,
		animContent: false,
		loadingShown: false,
		transition: false,
		resizing: false,
		closing: false,
		error: false,
		blocker: null,
		blockerVars: null,
		full: null,
		bg: null,
		loading: null,
		tmp: null,
		content: null,
		wrapper: null,
		contentWrapper: null,
		scripts: new Array(),
		scriptsShown: new Array()
	};

	// Indicate of the height or the width was resized, to reinit the currentsettings related to null
	var resized = {
		width: false,
		height: false,
		windowResizing: false
	};

	var initSettingsSize = {
		width: null,
		height: null,
		windowResizing: true
	};

	var windowResizeTimeout;


	// -------------------------------------------------------
	// Public function
	// -------------------------------------------------------

	// jQuery extension function. A paramater object could be used to overwrite the default settings
	$.fn.nyroModal = function(settings) {
		if (!this)
			return false;
		return this.each(function() {
			var me = $(this);
			if (this.nodeName.toLowerCase() == 'form') {
				me
				.unbind('submit.nyroModal')
				.bind('submit.nyroModal', function(e) {
					if(e.isDefaultPrevented())
						return false;
					if (me.data('nyroModalprocessing'))
						return true;
					if (this.enctype == 'multipart/form-data') {
						processModal($.extend(settings, {
							from: this
						}));
						return true;
					}
					e.preventDefault();
					processModal($.extend(settings, {
						from: this
					}));
					return false;
				});
			} else {
				me
				.unbind('click.nyroModal')
				.bind('click.nyroModal', function(e) {
					if(e.isDefaultPrevented())
						return false;
					e.preventDefault();
					processModal($.extend(settings, {
						from: this
					}));
					return false;
				});
			}
		});
	};

	// jQuery extension function to call manually the modal. A paramater object could be used to overwrite the default settings
	$.fn.nyroModalManual = function(settings) {
		if (!this.length)
			processModal(settings);
		return this.each(function(){
			processModal($.extend(settings, {
				from: this
			}));
		});
	};

	$.nyroModalManual = function(settings) {
		processModal(settings);
	};

	// Update the current settings
	// object settings
	// string deep1 first key where overwrite the settings
	// string deep2 second key where overwrite the settings
	$.nyroModalSettings = function(settings, deep1, deep2) {
		setCurrentSettings(settings, deep1, deep2);
		if (!deep1 && modal.started) {
			if (modal.bg && settings.bgColor)
				currentSettings.updateBgColor(modal, currentSettings, function(){});

			if (modal.contentWrapper && settings.title)
				setTitle();

			if (!modal.error && (settings.windowResizing || (!modal.resizing && (('width' in settings && settings.width == currentSettings.width) || ('height' in settings && settings.height == currentSettings.height))))) {
				modal.resizing = true;
				if (modal.contentWrapper)
					calculateSize(true);
				if (modal.contentWrapper && modal.contentWrapper.is(':visible') && !modal.animContent) {
					if (fixFF)
						modal.content.css({position: ''});
					currentSettings.resize(modal, currentSettings, function() {
						currentSettings.windowResizing = false;
						modal.resizing = false;
						if (fixFF)
							modal.content.css({position: 'fixed'});
						if ($.isFunction(currentSettings.endResize))
							currentSettings.endResize(modal, currentSettings);
					});
				}
			}
		}
	};

	// Remove the modal function
	$.nyroModalRemove = function() {
		removeModal();
	};

	// Go to the next image for a gallery
	// return false if nothing was done
	$.nyroModalNext = function() {
		var link = getGalleryLink(1);
		if (link)
			return link.nyroModalManual(getCurrentSettingsNew());
		return false;
	};

	// Go to the previous image for a gallery
	// return false if nothing was done
	$.nyroModalPrev = function() {
		var link = getGalleryLink(-1);
		if (link)
			return link.nyroModalManual(getCurrentSettingsNew());
		return false;
	};


	// -------------------------------------------------------
	// Default Settings
	// -------------------------------------------------------

	$.fn.nyroModal.settings = {
		debug: false, // Show the debug in the background

		blocker: false, // Element which will be blocked by the modal
		
		windowResize: true, // indicates if the modal should resize when the window is resized

		modal: false, // Esc key or click backgrdound enabling or not

		type: '', // nyroModal type (form, formData, iframe, image, etc...)
		forceType: null, // Used to force the type
		from: '', // Dom object where the call come from
		hash: '', // Eventual hash in the url

		processHandler: null, // Handler just before the real process

		selIndicator: 'nyroModalSel', // Value added when a form or Ajax is sent with a filter content

		formIndicator: 'nyroModal', // Value added when a form is sent

		content: null, // Raw content if type content is used

		bgColor: '#000000', // Background color

		ajax: {}, // Ajax option (url, data, type, success will be overwritten for a form, url and success only for an ajax call)

		swf: { // Swf player options if swf type is used.
			wmode: 'transparent'
		},

		width: null, // default Width If null, will be calculate automatically
		height: null, // default Height If null, will be calculate automatically

		minWidth: 400, // Minimum width
		minHeight: 300, // Minimum height

		resizable: true, // Indicate if the content is resizable. Will be set to false for swf
		autoSizable: true, // Indicate if the content is auto sizable. If not, the min size will be used

		padding: 25, // padding for the max modal size

		regexImg: '[^\.]\.(jpg|jpeg|png|tiff|gif|bmp)\s*$', // Regex to find images
		addImageDivTitle: false, // Indicate if the div title should be inserted
		defaultImgAlt: 'Image', // Default alt attribute for the images
		setWidthImgTitle: true, // Set the width to the image title
		ltr: true, // Left to Right by default. Put to false for Hebrew or Right to Left language

		gallery: null, // Gallery name if provided
		galleryLinks: '<a href="#" class="nyroModalPrev">Prev</a><a href="#"  class="nyroModalNext">Next</a>', // Use .nyroModalPrev and .nyroModalNext to set the navigation link
		galleryCounts: galleryCounts, // Callback to show the gallery count
		galleryLoop: false, // Indicate if the gallery should loop

		zIndexStart: 100,

		cssOpt: { // Default CSS option for the nyroModal Div. Some will be overwritten or updated when using IE6
			bg: {
				position: 'absolute',
				overflow: 'hidden',
				top: 0,
				left: 0,
				height: '100%',
				width: '100%'
			},
			wrapper: {
				position: 'absolute',
				top: '50%',
				left: '50%'
			},
			wrapper2: {
			},
			content: {
			},
			loading: {
				position: 'absolute',
				top: '50%',
				left: '50%',
				marginTop: '-50px',
				marginLeft: '-50px'
			}
		},

		wrap: { // Wrapper div used to style the modal regarding the content type
			div: '<div class="wrapper"></div>',
			ajax: '<div class="wrapper"></div>',
			form: '<div class="wrapper"></div>',
			formData: '<div class="wrapper"></div>',
			image: '<div class="wrapperImg"></div>',
			swf: '<div class="wrapperSwf"></div>',
			iframe: '<div class="wrapperIframe"></div>',
			iframeForm: '<div class="wrapperIframe"></div>',
			manual: '<div class="wrapper"></div>'
		},

		closeButton: '<a href="#" class="nyroModalClose" id="closeBut" title="close">Close</a>', // Adding automaticly as the first child of #nyroModalWrapper

		title: null, // Modal title
		titleFromIframe: true, // When using iframe in the same domain, try to get the title from it

		openSelector: '.nyroModal', // selector for open a new modal. will be used to parse automaticly at page loading
		closeSelector: '.nyroModalClose', // selector to close the modal

		contentLoading: '<a href="#" class="nyroModalClose">Cancel</a>', // Loading div content

		errorClass: 'error', // CSS Error class added to the loading div in case of error
		contentError: 'The requested content cannot be loaded.<br />Please try again later.<br /><a href="#" class="nyroModalClose">Close</a>', // Content placed in the loading div in case of error

		handleError: null, // Callback in case of error

		showBackground: showBackground, // Show background animation function
		hideBackground: hideBackground, // Hide background animation function

		endFillContent: null, // Will be called after filling and wraping the content, before parsing closeSelector and openSelector and showing the content
		showContent: showContent, // Show content animation function
		endShowContent: null, // Will be called once the content is shown
		beforeHideContent: null, // Will be called just before the modal closing
		hideContent: hideContent, // Hide content animation function

		showTransition: showTransition, // Show the transition animation (a modal is already shown and a new one is requested)
		hideTransition: hideTransition, // Hide the transition animation to show the content

		showLoading: showLoading, // show loading animation function
		hideLoading: hideLoading, // hide loading animation function

		resize: resize, // Resize animation function
		endResize: null, // Will be called one the content is resized

		updateBgColor: updateBgColor, // Change background color animation function

		endRemove: null // Will be called once the modal is totally gone
	};

	// -------------------------------------------------------
	// Private function
	// -------------------------------------------------------

	// Main function
	function processModal(settings) {
		if (modal.loadingShown || modal.transition || modal.anim)
			return;
		debug('processModal');
		modal.started = true;
		callingSettings = $.extend(true, settings);
		setDefaultCurrentSettings(settings);
		if (!modal.full)
			modal.blockerVars = modal.blocker = null;
		modal.error = false;
		modal.closing = false;
		modal.dataReady = false;
		modal.scripts = new Array();
		modal.scriptsShown = new Array();

		currentSettings.type = fileType();
		if (currentSettings.forceType) {
			if (!currentSettings.content)
				currentSettings.from = true;
			currentSettings.type = currentSettings.forceType;
			currentSettings.forceType = null;
		}

		if ($.isFunction(currentSettings.processHandler))
			currentSettings.processHandler(currentSettings);

		var from = currentSettings.from;
		var url = currentSettings.url;

		initSettingsSize.width = currentSettings.width;
		initSettingsSize.height = currentSettings.height;

		if (currentSettings.type == 'swf') {
			// Swf is transforming as a raw content
			setCurrentSettings({overflow: 'visible'}, 'cssOpt', 'content');
			currentSettings.content = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+currentSettings.width+'" height="'+currentSettings.height+'"><param name="movie" value="'+url+'"></param>';
			var tmp = '';
			$.each(currentSettings.swf, function(name, val) {
				currentSettings.content+= '<param name="'+name+'" value="'+val+'"></param>';
				tmp+= ' '+name+'="'+val+'"';
			});
			currentSettings.content+= '<embed src="'+url+'" type="application/x-shockwave-flash" width="'+currentSettings.width+'" height="'+currentSettings.height+'"'+tmp+'></embed></object>';
		}

		if (from) {
			var jFrom = $(from).blur();
			if (currentSettings.type == 'form') {
				var data = $(from).serializeArray();
				data.push({name: currentSettings.formIndicator, value: 1});
				if (currentSettings.selector)
					data.push({name: currentSettings.selIndicator, value: currentSettings.selector.substring(1)});
				showModal();
				$.ajax($.extend({}, currentSettings.ajax, {
						url: url,
						data: data,
						type: jFrom.attr('method') ? jFrom.attr('method') : 'get',
						success: ajaxLoaded,
						error: loadingError
					}));
				debug('Form Ajax Load: '+jFrom.attr('action'));
			} else if (currentSettings.type == 'formData') {
				// Form with data. We're using a hidden iframe
				initModal();
				jFrom.attr('target', 'nyroModalIframe');
				jFrom.attr('action', url);
				jFrom.prepend('<input type="hidden" name="'+currentSettings.formIndicator+'" value="1" />');
				if (currentSettings.selector)
					jFrom.prepend('<input type="hidden" name="'+currentSettings.selIndicator+'" value="'+currentSettings.selector.substring(1)+'" />');
				modal.tmp.html('<iframe frameborder="0" hspace="0" name="nyroModalIframe" src="javascript:\'\';"></iframe>');
				$('iframe', modal.tmp)
					.css({
						width: currentSettings.width,
						height: currentSettings.height
					})
					.error(loadingError)
					.load(formDataLoaded);
				debug('Form Data Load: '+jFrom.attr('action'));
				showModal();
				showContentOrLoading();
			} else if (currentSettings.type == 'image') {
				debug('Image Load: '+url);
				var title = jFrom.attr('title') || currentSettings.defaultImgAlt;
				initModal();
				modal.tmp.html('<img id="nyroModalImg" />').find('img').attr('alt', title);
				modal.tmp.css({lineHeight: 0});
				$('img', modal.tmp)
					.error(loadingError)
					.load(function() {
						debug('Image Loaded: '+this.src);
						$(this).unbind('load');
						var w = modal.tmp.width();
						var h = modal.tmp.height();
						modal.tmp.css({lineHeight: ''});
						resized.width = w;
						resized.height = h;
						setCurrentSettings({
							width: w,
							height: h,
							imgWidth: w,
							imgHeight: h
						});
						initSettingsSize.width = w;
						initSettingsSize.height = h;
						setCurrentSettings({overflow: 'visible'}, 'cssOpt', 'content');
						modal.dataReady = true;
						if (modal.loadingShown || modal.transition)
							showContentOrLoading();
					})
					.attr('src', url);
				showModal();
			} else if (currentSettings.type == 'iframeForm') {
				initModal();
				modal.tmp.html('<iframe frameborder="0" hspace="0" src="javascript:\'\';" name="nyroModalIframe" id="nyroModalIframe"></iframe>');
				debug('Iframe Form Load: '+url);
				$('iframe', modal.tmp).eq(0)
					.css({
						width: '100%',
						height: $.support.boxModel? '99%' : '100%'
					})
					.load(iframeLoaded);
				modal.dataReady = true;
				showModal();
			} else if (currentSettings.type == 'iframe') {
				initModal();
				modal.tmp.html('<iframe frameborder="0" hspace="0" src="javascript:\'\';" name="nyroModalIframe" id="nyroModalIframe"></iframe>');
				debug('Iframe Load: '+url);
				$('iframe', modal.tmp).eq(0)
					.css({
						width: '100%',
						height: $.support.boxModel? '99%' : '100%'
					})
					.load(iframeLoaded);
				modal.dataReady = true;
				showModal();
			} else if (currentSettings.type) {
				// Could be every other kind of type or a dom selector
				debug('Content: '+currentSettings.type);
				initModal();
				modal.tmp.html(currentSettings.content);
				var w = modal.tmp.width();
				var h = modal.tmp.height();
				var div = $(currentSettings.type);
				if (div.length) {
					setCurrentSettings({type: 'div'});
					w = div.width();
					h = div.height();
					if (contentElt)
						contentEltLast = contentElt;
					contentElt = div;
					modal.tmp.append(div.contents());
				}
				initSettingsSize.width = w;
				initSettingsSize.height = h;
				setCurrentSettings({
					width: w,
					height: h
				});
				if (modal.tmp.html())
					modal.dataReady = true;
				else
					loadingError();
				if (!modal.ready)
					showModal();
				else
					endHideContent();
			} else {
				debug('Ajax Load: '+url);
				setCurrentSettings({type: 'ajax'});
				var data = currentSettings.ajax.data || {};
				if (currentSettings.selector) {
					if (typeof data == "string") {
						data+= '&'+currentSettings.selIndicator+'='+currentSettings.selector.substring(1);
					} else {
						data[currentSettings.selIndicator] = currentSettings.selector.substring(1);
					}
				}
				showModal();
				$.ajax($.extend(true, currentSettings.ajax, {
					url: url,
					success: ajaxLoaded,
					error: loadingError,
					data: data
				}));
			}
		} else if (currentSettings.content) {
			// Raw content not from a DOM element
			debug('Content: '+currentSettings.type);
			setCurrentSettings({type: 'manual'});
			initModal();
			modal.tmp.html($('<div/>').html(currentSettings.content).contents());
			if (modal.tmp.html())
				modal.dataReady = true;
			else
				loadingError();
			showModal();
		} else {
			// What should we show here? nothing happen
		}
	}

	// Update the current settings
	// object settings
	// string deep1 first key where overwrite the settings
	// string deep2 second key where overwrite the settings
	function setDefaultCurrentSettings(settings) {
		debug('setDefaultCurrentSettings');
		currentSettings = $.extend(true, {}, $.fn.nyroModal.settings, settings);
		setMargin();
	}

	function setCurrentSettings(settings, deep1, deep2) {
		if (modal.started) {
			if (deep1 && deep2) {
				$.extend(true, currentSettings[deep1][deep2], settings);
			} else if (deep1) {
				$.extend(true, currentSettings[deep1], settings);
			} else {
				if (modal.animContent) {
					if ('width' in settings) {
						if (!modal.resizing) {
							settings.setWidth = settings.width;
							shouldResize = true;
						}
						delete settings['width'];
					}
					if ('height' in settings) {
						if (!modal.resizing) {
							settings.setHeight = settings.height;
							shouldResize = true;
						}
						delete settings['height'];
					}
				}
				$.extend(true, currentSettings, settings);
			}
		} else {
			if (deep1 && deep2) {
				$.extend(true, $.fn.nyroModal.settings[deep1][deep2], settings);
			} else if (deep1) {
				$.extend(true, $.fn.nyroModal.settings[deep1], settings);
			} else {
				$.extend(true, $.fn.nyroModal.settings, settings);
			}
		}
	}

	// Set the margin for postionning the element. Useful for IE6
	function setMarginScroll() {
		if (isIE6 && !modal.blocker) {
			if (document.documentElement) {
				currentSettings.marginScrollLeft = document.documentElement.scrollLeft;
				currentSettings.marginScrollTop = document.documentElement.scrollTop;
			} else {
				currentSettings.marginScrollLeft = document.body.scrollLeft;
				currentSettings.marginScrollTop = document.body.scrollTop;
			}
		} else {
			currentSettings.marginScrollLeft = 0;
			currentSettings.marginScrollTop = 0;
		}
	}

	// Set the margin for the content
	function setMargin() {
		setMarginScroll();
		currentSettings.marginLeft = -(currentSettings.width+currentSettings.borderW)/2;
		currentSettings.marginTop = -(currentSettings.height+currentSettings.borderH)/2;
		if (!modal.blocker) {
			currentSettings.marginLeft+= currentSettings.marginScrollLeft;
			currentSettings.marginTop+= currentSettings.marginScrollTop;
		}
	}

	// Set the margin for the current loading
	function setMarginLoading() {
		setMarginScroll();
		var outer = getOuter(modal.loading);
		currentSettings.marginTopLoading = -(modal.loading.height() + outer.h.border + outer.h.padding)/2;
		currentSettings.marginLeftLoading = -(modal.loading.width() + outer.w.border + outer.w.padding)/2;
		if (!modal.blocker) {
			currentSettings.marginLeftLoading+= currentSettings.marginScrollLeft;
			currentSettings.marginTopLoading+= currentSettings.marginScrollTop;
		}
	}

	// Set the modal Title
	function setTitle() {
		var title = $('h1#nyroModalTitle', modal.contentWrapper);
		if (title.length)
			title.text(currentSettings.title);
		else
			modal.contentWrapper.prepend('<h1 id="nyroModalTitle">'+currentSettings.title+'</h1>');
	}

	// Init the nyroModal div by settings the CSS elements and hide needed elements
	function initModal() {
		debug('initModal');
		if (!modal.full) {
			if (currentSettings.debug)
				setCurrentSettings({color: 'white'}, 'cssOpt', 'bg');

			var full = {
				zIndex: currentSettings.zIndexStart,
				position: 'fixed',
				top: 0,
				left: 0,
				width: '100%',
				height: '100%'
			};

			var contain = body;
			var iframeHideIE = '';
			if (currentSettings.blocker) {
				modal.blocker = contain = $(currentSettings.blocker);
				var pos = modal.blocker.offset();
				var w = modal.blocker.outerWidth();
				var h = modal.blocker.outerHeight();
				if (isIE6) {
					setCurrentSettings({
						height: '100%',
						width: '100%',
						top: 0,
						left: 0
					}, 'cssOpt', 'bg');
				}
				modal.blockerVars = {
					top: pos.top,
					left: pos.left,
					width: w,
					height: h
				};
				var plusTop = (/msie/.test(userAgent) ?0:getCurCSS(body.get(0), 'borderTopWidth'));
				var plusLeft = (/msie/.test(userAgent) ?0:getCurCSS(body.get(0), 'borderLeftWidth'));
				full = {
					position: 'absolute',
					top: pos.top + plusTop,
					left: pos.left + plusLeft,
					width: w,
					height: h
				};
			} else if (isIE6) {
				body.css({
					marginLeft: 0,
					marginRight: 0
				});
				var w = body.width();
				var h = $(window).height()+'px';
				if ($(window).height() >= body.outerHeight()) {
					h = body.outerHeight()+'px';
				} else
					w+= 20;
				w += 'px';
				body.css({
					width: w,
					height: h,
					position: 'static',
					overflow: 'hidden'
				});
				$('html').css({overflow: 'hidden'});
				setCurrentSettings({
					cssOpt: {
						bg: {
							position: 'absolute',
							zIndex: currentSettings.zIndexStart+1,
							height: '110%',
							width: '110%',
							top: currentSettings.marginScrollTop+'px',
							left: currentSettings.marginScrollLeft+'px'
						},
						wrapper: { zIndex: currentSettings.zIndexStart+2 },
						loading: { zIndex: currentSettings.zIndexStart+3 }
					}
				});

				iframeHideIE = $('<iframe id="nyroModalIframeHideIe" src="javascript:\'\';"></iframe>')
								.css($.extend({},
									currentSettings.cssOpt.bg, {
										opacity: 0,
										zIndex: 50,
										border: 'none'
									}));
			}

			contain.append($('<div id="nyroModalFull"><div id="nyroModalBg"></div><div id="nyroModalWrapper"><div id="nyroModalContent"></div></div><div id="nyrModalTmp"></div><div id="nyroModalLoading"></div></div>').hide());

			modal.full = $('#nyroModalFull')
				.css(full)
				.show();
			modal.bg = $('#nyroModalBg')
				.css($.extend({
						backgroundColor: currentSettings.bgColor
					}, currentSettings.cssOpt.bg))
				.before(iframeHideIE);
			modal.bg.bind('click.nyroModal', clickBg);
			modal.loading = $('#nyroModalLoading')
				.css(currentSettings.cssOpt.loading)
				.hide();
			modal.contentWrapper = $('#nyroModalWrapper')
				.css(currentSettings.cssOpt.wrapper)
				.hide();
			modal.content = $('#nyroModalContent');
			modal.tmp = $('#nyrModalTmp').hide();

			// To stop the mousewheel if the the plugin is available
			if ($.isFunction($.fn.mousewheel)) {
				modal.content.mousewheel(function(e, d) {
					var elt = modal.content.get(0);
					if ((d > 0 && elt.scrollTop == 0) ||
							(d < 0 && elt.scrollHeight - elt.scrollTop == elt.clientHeight)) {
						e.preventDefault();
						e.stopPropagation();
					}
				});
			}

			$(document).bind('keydown.nyroModal', keyHandler);
			modal.content.css({width: 'auto', height: 'auto'});
			modal.contentWrapper.css({width: 'auto', height: 'auto'});

			if (!currentSettings.blocker && currentSettings.windowResize) {
				$(window).bind('resize.nyroModal', function() {
					window.clearTimeout(windowResizeTimeout);
					windowResizeTimeout = window.setTimeout(windowResizeHandler, 200);
				});
			}
		}
	}

	function windowResizeHandler() {
		$.nyroModalSettings(initSettingsSize);
	}

	// Show the modal (ie: the background and then the loading if needed or the content directly)
	function showModal() {
		debug('showModal');
		if (!modal.ready) {
			initModal();
			modal.anim = true;
			currentSettings.showBackground(modal, currentSettings, endBackground);
		} else {
			modal.anim = true;
			modal.transition = true;
			currentSettings.showTransition(modal, currentSettings, function(){endHideContent();modal.anim=false;showContentOrLoading();});
		}
	}

	// Called when user click on background
	function clickBg(e) {
		if (!currentSettings.modal)
			removeModal();
	}
	
	// Used for the escape key or the arrow in the gallery type
	function keyHandler(e) {
		if (e.keyCode == 27) {
			if (!currentSettings.modal)
				removeModal();
		} else if (currentSettings.gallery && modal.ready && modal.dataReady && !modal.anim && !modal.transition) {
			if (e.keyCode == 39 || e.keyCode == 40) {
				e.preventDefault();
				$.nyroModalNext();
				return false;
			} else if (e.keyCode == 37 || e.keyCode == 38) {
				e.preventDefault();
				$.nyroModalPrev();
				return false;
			}
		}
	}

	// Determine the filetype regarding the link DOM element
	function fileType() {
		var from = currentSettings.from;

		var url;

		if (from && from.nodeName) {
			var jFrom = $(from);

			url = jFrom.attr(from.nodeName.toLowerCase() == 'form' ? 'action' : 'href');
			if (!url)
				url = location.href.substring(window.location.host.length+7);
			currentSettings.url = url;

			if (jFrom.attr('rev') == 'modal')
				currentSettings.modal = true;

			currentSettings.title = jFrom.attr('title');

			if (from && from.rel && from.rel.toLowerCase() != 'nofollow') {
				var indexSpace = from.rel.indexOf(' ');
				currentSettings.gallery = indexSpace > 0 ? from.rel.substr(0, indexSpace) : from.rel;
			}

			var imgType = imageType(url, from);
			if (imgType)
				return imgType;

			if (isSwf(url))
				return 'swf';

			var iframe = false;
			if (from.target && from.target.toLowerCase() == '_blank' || (from.hostname && from.hostname.replace(/:\d*$/,'') != window.location.hostname.replace(/:\d*$/,''))) {
				iframe = true;
			}
			if (from.nodeName.toLowerCase() == 'form') {
				if (iframe)
					return 'iframeForm';
				setCurrentSettings(extractUrlSel(url));
				if (jFrom.attr('enctype') == 'multipart/form-data')
					return 'formData';
				return 'form';
			}
			if (iframe)
				return 'iframe';
		} else {
			url = currentSettings.url;
			if (!currentSettings.content)
				currentSettings.from = true;

			if (!url)
				return null;

			if (isSwf(url))
				return 'swf';

			var reg1 = new RegExp("^http://|https://", "g");
			if (url.match(reg1))
				return 'iframe';
		}

		var imgType = imageType(url, from);
		if (imgType)
			return imgType;

		var tmp = extractUrlSel(url);
		setCurrentSettings(tmp);

		if (!tmp.url)
			return tmp.selector;
	}

	function imageType(url, from) {
		var image = new RegExp(currentSettings.regexImg, 'i');
		if (image.test(url)) {
			return 'image';
		}
	}

	function isSwf(url) {
		var swf = new RegExp('[^\.]\.(swf)\s*$', 'i');
		return swf.test(url);
	}

	function extractUrlSel(url) {
		var ret = {
			url: null,
			selector: null
		};

		if (url) {
			var hash = getHash(url);
			var hashLoc = getHash(window.location.href);
			var curLoc = window.location.href.substring(0, window.location.href.length - hashLoc.length);
			var req = url.substring(0, url.length - hash.length);

			if (req == curLoc || req == $('base').attr('href')) {
				ret.selector = hash;
			} else {
				ret.url = req;
				ret.selector = hash;
			}
		}
		return ret;
	}

	// Called when the content cannot be loaded or tiemout reached
	function loadingError() {
		debug('loadingError');

		modal.error = true;

		if (!modal.ready)
			return;

		if ($.isFunction(currentSettings.handleError))
			currentSettings.handleError(modal, currentSettings);

		modal.loading
			.addClass(currentSettings.errorClass)
			.html(currentSettings.contentError);
		$(currentSettings.closeSelector, modal.loading)
			.unbind('click.nyroModal')
			.bind('click.nyroModal', removeModal);
		setMarginLoading();
		modal.loading
			.css({
				marginTop: currentSettings.marginTopLoading+'px',
				marginLeft: currentSettings.marginLeftLoading+'px'
			});
	}

	// Put the content from modal.tmp to modal.content
	function fillContent() {
		debug('fillContent');
		if (!modal.tmp.html())
			return;

		modal.content.html(modal.tmp.contents());
		modal.tmp.empty();
		wrapContent();

		if (currentSettings.type == 'iframeForm') {
			$(currentSettings.from)
				.attr('target', 'nyroModalIframe')
				.data('nyroModalprocessing', 1)
				.submit()
				.attr('target', '_blank')
				.removeData('nyroModalprocessing');
		}

		if (!currentSettings.modal)
			modal.wrapper.prepend(currentSettings.closeButton);

		if ($.isFunction(currentSettings.endFillContent))
			currentSettings.endFillContent(modal, currentSettings);

		modal.content.append(modal.scripts);

		$(currentSettings.closeSelector, modal.contentWrapper)
			.unbind('click.nyroModal')
			.bind('click.nyroModal', removeModal);
		$(currentSettings.openSelector, modal.contentWrapper).nyroModal(getCurrentSettingsNew());
	}

	// Get the current settings to be used in new links
	function getCurrentSettingsNew() {
		return callingSettings;
		var currentSettingsNew = $.extend(true, {}, currentSettings);
		if (resized.width)
			currentSettingsNew.width = null;
		else
			currentSettingsNew.width = initSettingsSize.width;
		if (resized.height)
			currentSettingsNew.height = null;
		else
			currentSettingsNew.height = initSettingsSize.height;
		currentSettingsNew.cssOpt.content.overflow = 'auto';
		return currentSettingsNew;
	}

	// Wrap the content and update the modal size if needed
	function wrapContent() {
		debug('wrapContent');

		var wrap = $(currentSettings.wrap[currentSettings.type]);
		modal.content.append(wrap.children().remove());
		modal.contentWrapper.wrapInner(wrap);

		if (currentSettings.gallery) {
			// Set the action for the next and prev button (or remove them)
			modal.content.append(currentSettings.galleryLinks);

			gallery.links = $('[rel="'+currentSettings.gallery+'"], [rel^="'+currentSettings.gallery+' "]');
			gallery.index = gallery.links.index(currentSettings.from);

			if (currentSettings.galleryCounts && $.isFunction(currentSettings.galleryCounts))
				currentSettings.galleryCounts(gallery.index + 1, gallery.links.length, modal, currentSettings);

			var currentSettingsNew = getCurrentSettingsNew();

			var linkPrev = getGalleryLink(-1);
			if (linkPrev) {
				var prev = $('.nyroModalPrev', modal.contentWrapper)
					.attr('href', linkPrev.attr('href'))
					.click(function(e) {
						e.preventDefault();
						$.nyroModalPrev();
						return false;
					});
				if (isIE6 && currentSettings.type == 'swf') {
					prev.before($('<iframe id="nyroModalIframeHideIeGalleryPrev" src="javascript:\'\';"></iframe>').css({
											position: prev.css('position'),
											top: prev.css('top'),
											left: prev.css('left'),
											width: prev.width(),
											height: prev.height(),
											opacity: 0,
											border: 'none'
										}));
				}
			} else {
				$('.nyroModalPrev', modal.contentWrapper).remove();
			}
			var linkNext = getGalleryLink(1);
			if (linkNext) {
				var next = $('.nyroModalNext', modal.contentWrapper)
					.attr('href', linkNext.attr('href'))
					.click(function(e) {
						e.preventDefault();
						$.nyroModalNext();
						return false;
					});
				if (isIE6 && currentSettings.type == 'swf') {
					next.before($('<iframe id="nyroModalIframeHideIeGalleryNext" src="javascript:\'\';"></iframe>')
									.css($.extend({}, {
											position: next.css('position'),
											top: next.css('top'),
											left: next.css('left'),
											width: next.width(),
											height: next.height(),
											opacity: 0,
											border: 'none'
										})));
				}
			} else {
				$('.nyroModalNext', modal.contentWrapper).remove();
			}
		}

		calculateSize();
	}

	function getGalleryLink(dir) {
		if (currentSettings.gallery) {
			if (!currentSettings.ltr)
				dir *= -1;
			var index = gallery.index + dir;
			if (index >= 0 && index < gallery.links.length)
				return gallery.links.eq(index);
			else if (currentSettings.galleryLoop) {
				if (index < 0)
					return gallery.links.eq(gallery.links.length-1);
				else
					return gallery.links.eq(0);
			}
		}
		return false;
	}

	// Calculate the size for the contentWrapper
	function calculateSize(resizing) {
		debug('calculateSize');

		modal.wrapper = modal.contentWrapper.children('div:first');

		resized.width = false;
		resized.height = false;
		if (false && !currentSettings.windowResizing) {
			initSettingsSize.width = currentSettings.width;
			initSettingsSize.height = currentSettings.height;
		}

		if (currentSettings.autoSizable && (!currentSettings.width || !currentSettings.height)) {
			modal.contentWrapper
				.css({
					opacity: 0,
					width: 'auto',
					height: 'auto'
				})
				.show();
			var tmp = {
				width: 'auto',
				height: 'auto'
			};
			if (currentSettings.width) {
				tmp.width = currentSettings.width;
			} else if (currentSettings.type == 'iframe') {
				tmp.width = currentSettings.minWidth;
			}

			if (currentSettings.height) {
				tmp.height = currentSettings.height;
			} else if (currentSettings.type == 'iframe') {
				tmp.height = currentSettings.minHeight;
			}

			modal.content.css(tmp);
			if (!currentSettings.width) {
				currentSettings.width = modal.content.outerWidth(true);
				resized.width = true;
			}
			if (!currentSettings.height) {
				currentSettings.height = modal.content.outerHeight(true);
				resized.height = true;
			}
			modal.contentWrapper.css({opacity: 1});
			if (!resizing)
				modal.contentWrapper.hide();
		}

		if (currentSettings.type != 'image' && currentSettings.type != 'swf') {
			currentSettings.width = Math.max(currentSettings.width, currentSettings.minWidth);
			currentSettings.height = Math.max(currentSettings.height, currentSettings.minHeight);
		}

		var outerWrapper = getOuter(modal.contentWrapper);
		var outerWrapper2 = getOuter(modal.wrapper);
		var outerContent = getOuter(modal.content);

		var tmp = {
			content: {
				width: currentSettings.width,
				height: currentSettings.height
			},
			wrapper2: {
				width: currentSettings.width + outerContent.w.total,
				height: currentSettings.height + outerContent.h.total
			},
			wrapper: {
				width: currentSettings.width + outerContent.w.total + outerWrapper2.w.total,
				height: currentSettings.height + outerContent.h.total + outerWrapper2.h.total
			}
		};

		if (currentSettings.resizable) {
			var maxHeight = modal.blockerVars? modal.blockerVars.height : $(window).height()
								- outerWrapper.h.border
								- (tmp.wrapper.height - currentSettings.height);
			var maxWidth = modal.blockerVars? modal.blockerVars.width : $(window).width()
								- outerWrapper.w.border
								- (tmp.wrapper.width - currentSettings.width);
			maxHeight-= currentSettings.padding*2;
			maxWidth-= currentSettings.padding*2;

			if (tmp.content.height > maxHeight || tmp.content.width > maxWidth) {
				// We're gonna resize the modal as it will goes outside the view port
				if (currentSettings.type == 'image' || currentSettings.type == 'swf') {
					// An image is resized proportionnaly
					var useW = currentSettings.imgWidth?currentSettings.imgWidth : currentSettings.width;
					var useH = currentSettings.imgHeight?currentSettings.imgHeight : currentSettings.height;
					var diffW = tmp.content.width - useW;
					var diffH = tmp.content.height - useH;
						if (diffH < 0) diffH = 0;
						if (diffW < 0) diffW = 0;
					var calcH = maxHeight - diffH;
					var calcW = maxWidth - diffW;
					var ratio = Math.min(calcH/useH, calcW/useW);
					calcW = Math.floor(useW*ratio);
					calcH = Math.floor(useH*ratio);
					tmp.content.height = calcH + diffH;
					tmp.content.width = calcW + diffW;
				} else {
					// For an HTML content, we simply decrease the size
					tmp.content.height = Math.min(tmp.content.height, maxHeight);
					tmp.content.width = Math.min(tmp.content.width, maxWidth);
				}
				tmp.wrapper2 = {
						width: tmp.content.width + outerContent.w.total,
						height: tmp.content.height + outerContent.h.total
					};
				tmp.wrapper = {
						width: tmp.content.width + outerContent.w.total + outerWrapper2.w.total,
						height: tmp.content.height + outerContent.h.total + outerWrapper2.h.total
					};
			}
		}

		if (currentSettings.type == 'swf') {
			$('object, embed', modal.content)
				.attr('width', tmp.content.width)
				.attr('height', tmp.content.height);
		} else if (currentSettings.type == 'image') {
			$('img', modal.content).css({
				width: tmp.content.width,
				height: tmp.content.height
			});
		}

		modal.content.css($.extend({}, tmp.content, currentSettings.cssOpt.content));
		modal.wrapper.css($.extend({}, tmp.wrapper2, currentSettings.cssOpt.wrapper2));

		if (!resizing)
			modal.contentWrapper.css($.extend({}, tmp.wrapper, currentSettings.cssOpt.wrapper));

		if (currentSettings.type == 'image' && currentSettings.addImageDivTitle) {
			// Adding the title for the image
			$('img', modal.content).removeAttr('alt');
			var divTitle = $('div', modal.content);
			if (currentSettings.title != currentSettings.defaultImgAlt && currentSettings.title) {
				if (divTitle.length == 0) {
					divTitle = $('<div>'+currentSettings.title+'</div>');
					modal.content.append(divTitle);
				}
				if (currentSettings.setWidthImgTitle) {
					var outerDivTitle = getOuter(divTitle);
					divTitle.css({width: (tmp.content.width + outerContent.w.padding - outerDivTitle.w.total)+'px'});
				}
			} else if (divTitle.length = 0) {
				divTitle.remove();
			}
		}

		if (currentSettings.title)
			setTitle();

		tmp.wrapper.borderW = outerWrapper.w.border;
		tmp.wrapper.borderH = outerWrapper.h.border;

		setCurrentSettings(tmp.wrapper);
		setMargin();
	}

	function removeModal(e) {
		debug('removeModal');
		if (e)
			e.preventDefault();
		if (modal.full && modal.ready) {
			$(document).unbind('keydown.nyroModal');
			if (!currentSettings.blocker)
				$(window).unbind('resize.nyroModal');
			modal.ready = false;
			modal.anim = true;
			modal.closing = true;
			if (modal.loadingShown || modal.transition) {
				currentSettings.hideLoading(modal, currentSettings, function() {
						modal.loading.hide();
						modal.loadingShown = false;
						modal.transition = false;
						currentSettings.hideBackground(modal, currentSettings, endRemove);
					});
			} else {
				if (fixFF)
					modal.content.css({position: ''}); // Fix Issue #10, remove the attribute
				modal.wrapper.css({overflow: 'hidden'}); // Used to fix a visual issue when hiding
				modal.content.css({overflow: 'hidden'}); // Used to fix a visual issue when hiding
				$('iframe', modal.content).hide(); // Fix issue 359
				if ($.isFunction(currentSettings.beforeHideContent)) {
					currentSettings.beforeHideContent(modal, currentSettings, function() {
						currentSettings.hideContent(modal, currentSettings, function() {
							endHideContent();
							currentSettings.hideBackground(modal, currentSettings, endRemove);
						});
					});
				} else {
					currentSettings.hideContent(modal, currentSettings, function() {
							endHideContent();
							currentSettings.hideBackground(modal, currentSettings, endRemove);
						});
				}
			}
		}
		if (e)
			return false;
	}

	function showContentOrLoading() {
		debug('showContentOrLoading');
		if (modal.ready && !modal.anim) {
			if (modal.dataReady) {
				if (modal.tmp.html()) {
					modal.anim = true;
					if (modal.transition) {
						fillContent();
						modal.animContent = true;
						currentSettings.hideTransition(modal, currentSettings, function() {
							modal.loading.hide();
							modal.transition = false;
							modal.loadingShown = false;
							endShowContent();
						});
					} else {
						currentSettings.hideLoading(modal, currentSettings, function() {
								modal.loading.hide();
								modal.loadingShown = false;
								fillContent();
								setMarginLoading();
								setMargin();
								modal.animContent = true;
								currentSettings.showContent(modal, currentSettings, endShowContent);
							});
					}
				}
			} else if (!modal.loadingShown && !modal.transition) {
				modal.anim = true;
				modal.loadingShown = true;
				if (modal.error)
					loadingError();
				else
					modal.loading.html(currentSettings.contentLoading);
				$(currentSettings.closeSelector, modal.loading)
					.unbind('click.nyroModal')
					.bind('click.nyroModal', removeModal);
				setMarginLoading();
				currentSettings.showLoading(modal, currentSettings, function(){modal.anim=false;showContentOrLoading();});
			}
		}
	}
	
	// -------------------------------------------------------
	// Private Data Loaded callback
	// -------------------------------------------------------

	function ajaxLoaded(data) {
		debug('AjaxLoaded: '+this.url);
		
		if (currentSettings.selector) {
			var tmp = {};
			var i = 0;
			// Looking for script to store them
			data = data
				.replace(/\r\n/gi,'nyroModalLN')
				.replace(/<script(.|\s)*?\/script>/gi, function(x) {
						tmp[i] = x;
						return '<pre style="display: none" class=nyroModalScript rel="'+(i++)+'"></pre>';
					});
			data = $('<div>'+data+'</div>').find(currentSettings.selector).html()
				.replace(/<pre style="display: none;?" class="?nyroModalScript"? rel="(.?)"><\/pre>/gi, function(x, y, z) {
					return tmp[y];
				})
				.replace(/nyroModalLN/gi,"\r\n");
		}
		modal.tmp.html(filterScripts(data));
		if (modal.tmp.html()) {
			modal.dataReady = true;
			showContentOrLoading();
		} else
			loadingError();
	}

	function formDataLoaded() {
		debug('formDataLoaded');
		var jFrom = $(currentSettings.from);
		jFrom.attr('action', jFrom.attr('action')+currentSettings.selector);
		jFrom.attr('target', '');
		$('input[name='+currentSettings.formIndicator+']', currentSettings.from).remove();
		var iframe = modal.tmp.children('iframe');
		var iframeContent = iframe.unbind('load').contents().find(currentSettings.selector || 'body').not('script[src]');
		iframe.attr('src', 'about:blank'); // Used to stop the loading in FF
		modal.tmp.html(iframeContent.html());
		if (modal.tmp.html()) {
			modal.dataReady = true;
			showContentOrLoading();
		} else
			loadingError();
	}
	
	function iframeLoaded() {
		if ((window.location.hostname && currentSettings.url.indexOf(window.location.hostname) > -1)
				||	currentSettings.url.indexOf('http://')) {
			var iframe = $('iframe', modal.full).contents();
			var tmp = {};
			if (currentSettings.titleFromIframe) {
				tmp.title = iframe.find('title').text();
				if (!tmp.title) {
					// for IE
					try {
						tmp.title = iframe.find('title').html();
					} catch(err) {}
				}
			}
			var body = iframe.find('body');
			if (!currentSettings.height && body.height())
				tmp.height = body.height();
			if (!currentSettings.width && body.width())
				tmp.width = body.width();
			$.extend(initSettingsSize, tmp);
			$.nyroModalSettings(tmp);
		}
	}

	function galleryCounts(nb, total, elts, settings) {
		if (total > 1)
			settings.title+= (settings.title?' - ':'') +nb+'/'+total;
	}


	// -------------------------------------------------------
	// Private Animation callback
	// -------------------------------------------------------

	function endHideContent() {
		debug('endHideContent');
		modal.anim = false;
		if (contentEltLast) {
			contentEltLast.append(modal.content.contents());
			contentEltLast = null;
		} else if (contentElt) {
			contentElt.append(modal.content.contents());
			contentElt= null;
		}
		modal.content.empty();

		gallery = {};

		modal.contentWrapper.hide().children().remove().empty().attr('style', '').hide();

		if (modal.closing || modal.transition)
			modal.contentWrapper.hide();

		modal.contentWrapper
			.css(currentSettings.cssOpt.wrapper)
			.append(modal.content);
		showContentOrLoading();
	}

	function endRemove() {
		debug('endRemove');
		$(document).unbind('keydown', keyHandler);
		modal.anim = false;
		modal.full.remove();
		modal.full = null;
		if (isIE6) {
			body.css({height: '', width: '', position: '', overflow: '', marginLeft: '', marginRight: ''});
			$('html').css({overflow: ''});
		}
		if ($.isFunction(currentSettings.endRemove))
			currentSettings.endRemove(modal, currentSettings);
	}

	function endBackground() {
		debug('endBackground');
		modal.ready = true;
		modal.anim = false;
		showContentOrLoading();
	}

	function endShowContent() {
		debug('endShowContent');
		modal.anim = false;
		modal.animContent = false;
		modal.contentWrapper.css({opacity: ''}); // for the close button in IE
		fixFF = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) && parseFloat(browserVersion) < 1.9 && currentSettings.type != 'image';

		if (fixFF)
			modal.content.css({position: 'fixed'}); // Fix Issue #10
		modal.content.append(modal.scriptsShown);

		if(currentSettings.type == 'iframe')
			modal.content.find('iframe').attr('src', currentSettings.url);

		if ($.isFunction(currentSettings.endShowContent))
			currentSettings.endShowContent(modal, currentSettings);

		if (shouldResize) {
			shouldResize = false;
			$.nyroModalSettings({width: currentSettings.setWidth, height: currentSettings.setHeight});
			delete currentSettings['setWidth'];
			delete currentSettings['setHeight'];
		}
		if (resized.width)
			setCurrentSettings({width: null});
		if (resized.height)
			setCurrentSettings({height: null});
	}


	// -------------------------------------------------------
	// Utilities
	// -------------------------------------------------------

	// Get the selector from an url (as string)
	function getHash(url) {
		if (typeof url == 'string') {
			var hashPos = url.indexOf('#');
			if (hashPos > -1)
				return url.substring(hashPos);
		}
		return '';
	}

	// Filter an html content to remove the script[src]
	function filterScripts(data) {
		// Removing the body, head and html tag
		if (typeof data == 'string')
			data = data.replace(/<\/?(html|head|body)([^>]*)>/gi, '');
		var tmp = new Array();
		$.each($.clean({0:data}, this.ownerDocument), function() {
			if ($.nodeName(this, "script")) {
				if (!this.src || $(this).attr('rel') == 'forceLoad') {
					if ($(this).attr('rev') == 'shown')
						modal.scriptsShown.push(this);
					else
						modal.scripts.push(this);
				}
			} else
				tmp.push(this);
		});
		return tmp;
	}

	// Get the vertical and horizontal margin, padding and border dimension
	function getOuter(elm) {
		elm = elm.get(0);
		var ret = {
			h: {
				margin: getCurCSS(elm, 'marginTop') + getCurCSS(elm, 'marginBottom'),
				border: getCurCSS(elm, 'borderTopWidth') + getCurCSS(elm, 'borderBottomWidth'),
				padding: getCurCSS(elm, 'paddingTop') + getCurCSS(elm, 'paddingBottom')
			},
			w: {
				margin: getCurCSS(elm, 'marginLeft') + getCurCSS(elm, 'marginRight'),
				border: getCurCSS(elm, 'borderLeftWidth') + getCurCSS(elm, 'borderRightWidth'),
				padding: getCurCSS(elm, 'paddingLeft') + getCurCSS(elm, 'paddingRight')
			}
		};

		ret.h.outer = ret.h.margin + ret.h.border;
		ret.w.outer = ret.w.margin + ret.w.border;

		ret.h.inner = ret.h.padding + ret.h.border;
		ret.w.inner = ret.w.padding + ret.w.border;

		ret.h.total = ret.h.outer + ret.h.padding;
		ret.w.total = ret.w.outer + ret.w.padding;

		return ret;
	}

	function getCurCSS(elm, name) {
		var ret = parseInt($.curCSS(elm, name, true));
		if (isNaN(ret))
			ret = 0;
		return ret;
	}

	// Proxy Debug function
	function debug(msg) {
		if ($.fn.nyroModal.settings.debug || currentSettings && currentSettings.debug)
			nyroModalDebug(msg, modal, currentSettings || {});
	}

	// -------------------------------------------------------
	// Default animation function
	// -------------------------------------------------------

	function showBackground(elts, settings, callback) {
		elts.bg.css({opacity:0}).fadeTo(500, 0.8, callback);
	}

	function hideBackground(elts, settings, callback) {
		elts.bg.fadeOut(300, callback);
	}

	function showLoading(elts, settings, callback) {
		elts.loading
			.css({
				marginTop: settings.marginTopLoading+'px',
				marginLeft: settings.marginLeftLoading+'px',
				opacity: 0
			})
			.show()
			.animate({
				opacity: 1
			}, {complete: callback, duration: 400});
	}

	function hideLoading(elts, settings, callback) {
		callback();
	}

	function showContent(elts, settings, callback) {
		elts.loading
			.css({
				marginTop: settings.marginTopLoading+'px',
				marginLeft: settings.marginLeftLoading+'px'
			})
			.show()
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginTop: settings.marginTop+'px',
				marginLeft: settings.marginLeft+'px'
			}, {duration: 350, complete: function() {
				elts.contentWrapper
					.css({
						width: settings.width+'px',
						height: settings.height+'px',
						marginTop: settings.marginTop+'px',
						marginLeft: settings.marginLeft+'px'
					})
					.show();
					elts.loading.fadeOut(200, callback);
				}
			});
	}

	function hideContent(elts, settings, callback) {
		elts.contentWrapper
			.animate({
				height: '50px',
				width: '50px',
				marginTop: (-(25+settings.borderH)/2 + settings.marginScrollTop)+'px',
				marginLeft: (-(25+settings.borderW)/2 + settings.marginScrollLeft)+'px'
			}, {duration: 350, complete: function() {
				elts.contentWrapper.hide();
				callback();
			}});
	}

	function showTransition(elts, settings, callback) {
		// Put the loading with the same dimensions of the current content
		elts.loading
			.css({
				marginTop: elts.contentWrapper.css('marginTop'),
				marginLeft: elts.contentWrapper.css('marginLeft'),
				height: elts.contentWrapper.css('height'),
				width: elts.contentWrapper.css('width'),
				opacity: 0
			})
			.show()
			.fadeTo(400, 1, function() {
					elts.contentWrapper.hide();
					callback();
				});
	}

	function hideTransition(elts, settings, callback) {
		// Place the content wrapper underneath the the loading with the right dimensions
		elts.contentWrapper
			.hide()
			.css({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px',
				opacity: 1
			});
		elts.loading
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px'
			}, {complete: function() {
					elts.contentWrapper.show();
					elts.loading.fadeOut(400, function() {
						elts.loading.hide();
						callback();
					});
				}, duration: 350});
	}

	function resize(elts, settings, callback) {
		elts.contentWrapper
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px'
			}, {complete: callback, duration: 400});
	}

	function updateBgColor(elts, settings, callback) {
		if (!$.fx.step.backgroundColor) {
			elts.bg.css({backgroundColor: settings.bgColor});
			callback();
		} else
			elts.bg
				.animate({
					backgroundColor: settings.bgColor
				}, {complete: callback, duration: 400});
	}

	// -------------------------------------------------------
	// Default initialization
	// -------------------------------------------------------

	$($.fn.nyroModal.settings.openSelector).nyroModal();

});

// Default debug function, to be overwritten if needed
//      Be aware that the settings parameter could be empty
var tmpDebug = '';
function nyroModalDebug(msg, elts, settings) {
	if (elts.full && elts.bg) {
		elts.bg.prepend(msg+'<br />'+tmpDebug);
		tmpDebug = '';
	} else
		tmpDebug+= msg+'<br />';
}


/*

 * jQuery validation plug-in pre-1.5.2

 *

 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/

 * http://docs.jquery.com/Plugins/Validation

 *

 * Copyright (c) 2006 - 2008 Jörn Zaefferer

 *

 * $Id: jquery.validate.js 6243 2009-02-19 11:40:49Z joern.zaefferer $

 *

 * Dual licensed under the MIT and GPL licenses:

 *   http://www.opensource.org/licenses/mit-license.php

 *   http://www.gnu.org/licenses/gpl.html

 */



(function($) {



$.extend($.fn, {

	// http://docs.jquery.com/Plugins/Validation/validate

	validate: function( options ) {

		

		// if nothing is selected, return nothing; can't chain anyway

		if (!this.length) {

			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );

			return;

		}

		

		// check if a validator for this form was already created

		var validator = $.data(this[0], 'validator');

		if ( validator ) {

			return validator;

		}

		

		validator = new $.validator( options, this[0] );

		$.data(this[0], 'validator', validator); 

		

		if ( validator.settings.onsubmit ) {

		

			// allow suppresing validation by adding a cancel class to the submit button

			this.find("input, button").filter(".cancel").click(function() {

				validator.cancelSubmit = true;

			});

		

			// validate the form on submit

			this.submit( function( event ) {

				if ( validator.settings.debug )

					// prevent form submit to be able to see console output

					event.preventDefault();

					

				function handle() {

					if ( validator.settings.submitHandler ) {

						validator.settings.submitHandler.call( validator, validator.currentForm );

						return false;

					}

					return true;

				}

					

				// prevent submit for invalid forms or custom submit handlers

				if ( validator.cancelSubmit ) {

					validator.cancelSubmit = false;

					return handle();

				}

				if ( validator.form() ) {

					if ( validator.pendingRequest ) {

						validator.formSubmitted = true;

						return false;

					}

					return handle();

				} else {

					validator.focusInvalid();

					return false;

				}

			});

		}

		

		return validator;

	},

	// http://docs.jquery.com/Plugins/Validation/valid

	valid: function() {

        if ( $(this[0]).is('form')) {

            return this.validate().form();

        } else {

            var valid = false;

            var validator = $(this[0].form).validate();

            this.each(function() {

				valid |= validator.element(this);

            });

            return valid;

        }

    },

	// attributes: space seperated list of attributes to retrieve and remove

	removeAttrs: function(attributes) {

		var result = {},

			$element = this;

		$.each(attributes.split(/\s/), function(index, value) {

			result[value] = $element.attr(value);

			$element.removeAttr(value);

		});

		return result;

	},

	// http://docs.jquery.com/Plugins/Validation/rules

	rules: function(command, argument) {

		var element = this[0];

		

		if (command) {

			var settings = $.data(element.form, 'validator').settings;

			var staticRules = settings.rules;

			var existingRules = $.validator.staticRules(element);

			switch(command) {

			case "add":

				$.extend(existingRules, $.validator.normalizeRule(argument));

				staticRules[element.name] = existingRules;

				if (argument.messages)

					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );

				break;

			case "remove":

				if (!argument) {

					delete staticRules[element.name];

					return existingRules;

				}

				var filtered = {};

				$.each(argument.split(/\s/), function(index, method) {

					filtered[method] = existingRules[method];

					delete existingRules[method];

				});

				return filtered;

			}

		}

		

		var data = $.validator.normalizeRules(

		$.extend(

			{},

			$.validator.metadataRules(element),

			$.validator.classRules(element),

			$.validator.attributeRules(element),

			$.validator.staticRules(element)

		), element);

		

		// make sure required is at front

		if (data.required) {

			var param = data.required;

			delete data.required;

			data = $.extend({required: param}, data);

		}

		

		return data;

	}

});



// Custom selectors

$.extend($.expr[":"], {

	// http://docs.jquery.com/Plugins/Validation/blank

	blank: function(a) {return !$.trim(a.value);},

	// http://docs.jquery.com/Plugins/Validation/filled

	filled: function(a) {return !!$.trim(a.value);},

	// http://docs.jquery.com/Plugins/Validation/unchecked

	unchecked: function(a) {return !a.checked;}

});





$.format = function(source, params) {

	if ( arguments.length == 1 ) 

		return function() {

			var args = $.makeArray(arguments);

			args.unshift(source);

			return $.format.apply( this, args );

		};

	if ( arguments.length > 2 && params.constructor != Array  ) {

		params = $.makeArray(arguments).slice(1);

	}

	if ( params.constructor != Array ) {

		params = [ params ];

	}

	$.each(params, function(i, n) {

		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);

	});

	return source;

};



// constructor for validator

$.validator = function( options, form ) {

	this.settings = $.extend( {}, $.validator.defaults, options );

	this.currentForm = form;

	this.init();

};



$.extend($.validator, {



	defaults: {

		messages: {},

		groups: {},

		rules: {},

		errorClass: "error",

		errorElement: "label",

		focusInvalid: true,

		errorContainer: $( [] ),

		errorLabelContainer: $( [] ),

		onsubmit: true,

		ignore: [],

		ignoreTitle: false,

		onfocusin: function(element) {

			this.lastActive = element;

				

			// hide error label and remove error class on focus if enabled

			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {

				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );

				this.errorsFor(element).hide();

			}

		},

		onfocusout: function(element) {

			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {

				this.element(element);

			}

		},

		onkeyup: function(element) {

			if ( element.name in this.submitted || element == this.lastElement ) {

				this.element(element);

			}

		},

		onclick: function(element) {

			if ( element.name in this.submitted )

				this.element(element);

		},

		highlight: function( element, errorClass ) {

			$( element ).addClass( errorClass );

		},

		unhighlight: function( element, errorClass ) {

			$( element ).removeClass( errorClass );

		}

	},



	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults

	setDefaults: function(settings) {

		$.extend( $.validator.defaults, settings );

	},



	messages: {

		required: "This field is required.",

		remote: "Please fix this field.",

		email: "Please enter a valid email address.",

		url: "Please enter a valid URL.",

		date: "Please enter a valid date.",

		dateISO: "Please enter a valid date (ISO).",

		dateDE: "Bitte geben Sie ein gültiges Datum ein.",

		number: "Please enter a valid number.",

		numberDE: "Bitte geben Sie eine Nummer ein.",

		digits: "Please enter only digits",

		creditcard: "Please enter a valid credit card number.",

		equalTo: "Please enter the same value again.",

		accept: "Please enter a value with a valid extension.",

		maxlength: $.format("Please enter no more than {0} characters."),

		minlength: $.format("Please enter at least {0} characters."),

		rangelength: $.format("Please enter a value between {0} and {1} characters long."),

		range: $.format("Please enter a value between {0} and {1}."),

		max: $.format("Please enter a value less than or equal to {0}."),

		min: $.format("Please enter a value greater than or equal to {0}.")

	},

	

	autoCreateRanges: false,

	

	prototype: {

		

		init: function() {

			this.labelContainer = $(this.settings.errorLabelContainer);

			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);

			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );

			this.submitted = {};

			this.valueCache = {};

			this.pendingRequest = 0;

			this.pending = {};

			this.invalid = {};

			this.reset();

			

			var groups = (this.groups = {});

			$.each(this.settings.groups, function(key, value) {

				$.each(value.split(/\s/), function(index, name) {

					groups[name] = key;

				});

			});

			var rules = this.settings.rules;

			$.each(rules, function(key, value) {

				rules[key] = $.validator.normalizeRule(value);

			});

			

			function delegate(event) {

				var validator = $.data(this[0].form, "validator");

				validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );

			}

			$(this.currentForm)

				.delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)

				.delegate("click", ":radio, :checkbox", delegate);



			if (this.settings.invalidHandler)

				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);

		},



		// http://docs.jquery.com/Plugins/Validation/Validator/form

		form: function() {

			this.checkForm();

			$.extend(this.submitted, this.errorMap);

			this.invalid = $.extend({}, this.errorMap);

			if (!this.valid())

				$(this.currentForm).triggerHandler("invalid-form", [this]);

			this.showErrors();

			return this.valid();

		},

		

		checkForm: function() {

			this.prepareForm();

			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {

				this.check( elements[i] );

			}

			return this.valid(); 

		},

		

		// http://docs.jquery.com/Plugins/Validation/Validator/element

		element: function( element ) {

			element = this.clean( element );

			this.lastElement = element;

			this.prepareElement( element );

			this.currentElements = $(element);

			var result = this.check( element );

			if ( result ) {

				delete this.invalid[element.name];

			} else {

				this.invalid[element.name] = true;

			}

			if ( !this.numberOfInvalids() ) {

				// Hide error containers on last error

				this.toHide = this.toHide.add( this.containers );

			}

			this.showErrors();

			return result;

		},



		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors

		showErrors: function(errors) {

			if(errors) {

				// add items to error list and map

				$.extend( this.errorMap, errors );

				this.errorList = [];

				for ( var name in errors ) {

					this.errorList.push({

						message: errors[name],

						element: this.findByName(name)[0]

					});

				}

				// remove items from success list

				this.successList = $.grep( this.successList, function(element) {

					return !(element.name in errors);

				});

			}

			this.settings.showErrors

				? this.settings.showErrors.call( this, this.errorMap, this.errorList )

				: this.defaultShowErrors();

		},

		

		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm

		resetForm: function() {

			if ( $.fn.resetForm )

				$( this.currentForm ).resetForm();

			this.submitted = {};

			this.prepareForm();

			this.hideErrors();

			this.elements().removeClass( this.settings.errorClass );

		},

		

		numberOfInvalids: function() {

			return this.objectLength(this.invalid);

		},

		

		objectLength: function( obj ) {

			var count = 0;

			for ( var i in obj )

				count++;

			return count;

		},

		

		hideErrors: function() {

			this.addWrapper( this.toHide ).hide();

		},

		

		valid: function() {

			return this.size() == 0;

		},

		

		size: function() {

			return this.errorList.length;

		},

		

		focusInvalid: function() {

			if( this.settings.focusInvalid ) {

				try {

					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();

				} catch(e) {

					// ignore IE throwing errors when focusing hidden elements

				}

			}

		},

		

		findLastActive: function() {

			var lastActive = this.lastActive;

			return lastActive && $.grep(this.errorList, function(n) {

				return n.element.name == lastActive.name;

			}).length == 1 && lastActive;

		},

		

		elements: function() {

			var validator = this,

				rulesCache = {};

			

			// select all valid inputs inside the form (no submit or reset buttons)

			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved

			return $([]).add(this.currentForm.elements)

			.filter(":input")

			.not(":submit, :reset, :image, [disabled]")

			.not( this.settings.ignore )

			.filter(function() {

				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

			

				// select only the first element for each name, and only those with rules specified

				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )

					return false;

				

				rulesCache[this.name] = true;

				return true;

			});

		},

		

		clean: function( selector ) {

			return $( selector )[0];

		},

		

		errors: function() {

			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );

		},

		

		reset: function() {

			this.successList = [];

			this.errorList = [];

			this.errorMap = {};

			this.toShow = $([]);

			this.toHide = $([]);

			this.formSubmitted = false;

			this.currentElements = $([]);

		},

		

		prepareForm: function() {

			this.reset();

			this.toHide = this.errors().add( this.containers );

		},

		

		prepareElement: function( element ) {

			this.reset();

			this.toHide = this.errorsFor(element);

		},

	

		check: function( element ) {

			element = this.clean( element );

			

			// if radio/checkbox, validate first element in group instead

			if (this.checkable(element)) {

				element = this.findByName( element.name )[0];

			}

			

			var rules = $(element).rules();

			var dependencyMismatch = false;

			for( method in rules ) {

				var rule = { method: method, parameters: rules[method] };

				try {

					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );

					

					// if a method indicates that the field is optional and therefore valid,

					// don't mark it as valid when there are no other rules

					if ( result == "dependency-mismatch" ) {

						dependencyMismatch = true;

						continue;

					}

					dependencyMismatch = false;

					

					if ( result == "pending" ) {

						this.toHide = this.toHide.not( this.errorsFor(element) );

						return;

					}

					

					if( !result ) {

						this.formatAndAdd( element, rule );

						return false;

					}

				} catch(e) {

					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id

						 + ", check the '" + rule.method + "' method");

					throw e;

				}

			}

			if (dependencyMismatch)

				return;

			if ( this.objectLength(rules) )

				this.successList.push(element);

			return true;

		},

		

		// return the custom message for the given element and validation method

		// specified in the element's "messages" metadata

		customMetaMessage: function(element, method) {

			if (!$.metadata)

				return;

			

			var meta = this.settings.meta

				? $(element).metadata()[this.settings.meta]

				: $(element).metadata();

			

			return meta && meta.messages && meta.messages[method];

		},

		

		// return the custom message for the given element name and validation method

		customMessage: function( name, method ) {

			var m = this.settings.messages[name];

			return m && (m.constructor == String

				? m

				: m[method]);

		},

		

		// return the first defined argument, allowing empty strings

		findDefined: function() {

			for(var i = 0; i < arguments.length; i++) {

				if (arguments[i] !== undefined)

					return arguments[i];

			}

			return undefined;

		},

		

		defaultMessage: function( element, method) {

			return this.findDefined(

				this.customMessage( element.name, method ),

				this.customMetaMessage( element, method ),

				// title is never undefined, so handle empty string as undefined

				!this.settings.ignoreTitle && element.title || undefined,

				$.validator.messages[method],

				"<strong>Warning: No message defined for " + element.name + "</strong>"

			);

		},

		

		formatAndAdd: function( element, rule ) {

			var message = this.defaultMessage( element, rule.method );

			if ( typeof message == "function" ) 

				message = message.call(this, rule.parameters, element);

			this.errorList.push({

				message: message,

				element: element

			});

			this.errorMap[element.name] = message;

			this.submitted[element.name] = message;

		},

		

		addWrapper: function(toToggle) {

			if ( this.settings.wrapper )

				toToggle = toToggle.add( toToggle.parents( this.settings.wrapper ) );

			return toToggle;

		},

		

		defaultShowErrors: function() {

			for ( var i = 0; this.errorList[i]; i++ ) {

				var error = this.errorList[i];

				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );

				this.showLabel( error.element, error.message );

			}

			if( this.errorList.length ) {

				this.toShow = this.toShow.add( this.containers );

			}

			if (this.settings.success) {

				for ( var i = 0; this.successList[i]; i++ ) {

					this.showLabel( this.successList[i] );

				}

			}

			if (this.settings.unhighlight) {

				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {

					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass );

				}

			}

			this.toHide = this.toHide.not( this.toShow );

			this.hideErrors();

			this.addWrapper( this.toShow ).show();

		},

		

		validElements: function() {

			return this.currentElements.not(this.invalidElements());

		},

		

		invalidElements: function() {

			return $(this.errorList).map(function() {

				return this.element;

			});

		},

		

		showLabel: function(element, message) {

			var label = this.errorsFor( element );

			if ( label.length ) {

				// refresh error/success class

				label.removeClass().addClass( this.settings.errorClass );

			

				// check if we have a generated label, replace the message then

				label.attr("generated") && label.html(message);

			} else {

				// create label

				label = $("<" + this.settings.errorElement + "/>")

					.attr({"for":  this.idOrName(element), generated: true})

					.addClass(this.settings.errorClass)

					.html(message || "");

				if ( this.settings.wrapper ) {

					// make sure the element is visible, even in IE

					// actually showing the wrapped element is handled elsewhere

					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();

				}

				if ( !this.labelContainer.append(label).length )

					this.settings.errorPlacement

						? this.settings.errorPlacement(label, $(element) )

						: label.insertAfter(element);

			}

			if ( !message && this.settings.success ) {

				label.text("");

				typeof this.settings.success == "string"

					? label.addClass( this.settings.success )

					: this.settings.success( label );

			}

			this.toShow = this.toShow.add(label);

		},

		

		errorsFor: function(element) {

			return this.errors().filter("[for='" + this.idOrName(element) + "']");

		},

		

		idOrName: function(element) {

			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);

		},



		checkable: function( element ) {

			return /radio|checkbox/i.test(element.type);

		},

		

		findByName: function( name ) {

			// select by name and filter by form for performance over form.find("[name=...]")

			var form = this.currentForm;

			return $(document.getElementsByName(name)).map(function(index, element) {

				return element.form == form && element.name == name && element  || null;

			});

		},

		

		getLength: function(value, element) {

			switch( element.nodeName.toLowerCase() ) {

			case 'select':

				return $("option:selected", element).length;

			case 'input':

				if( this.checkable( element) )

					return this.findByName(element.name).filter(':checked').length;

			}

			return value.length;

		},

	

		depend: function(param, element) {

			return this.dependTypes[typeof param]

				? this.dependTypes[typeof param](param, element)

				: true;

		},

	

		dependTypes: {

			"boolean": function(param, element) {

				return param;

			},

			"string": function(param, element) {

				return !!$(param, element.form).length;

			},

			"function": function(param, element) {

				return param(element);

			}

		},

		

		optional: function(element) {

			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";

		},

		

		startRequest: function(element) {

			if (!this.pending[element.name]) {

				this.pendingRequest++;

				this.pending[element.name] = true;

			}

		},

		

		stopRequest: function(element, valid) {

			this.pendingRequest--;

			// sometimes synchronization fails, make sure pendingRequest is never < 0

			if (this.pendingRequest < 0)

				this.pendingRequest = 0;

			delete this.pending[element.name];

			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {

				$(this.currentForm).submit();

			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {

				$(this.currentForm).triggerHandler("invalid-form", [this]);

			}

		},

		

		previousValue: function(element) {

			return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {

				old: null,

				valid: true,

				message: this.defaultMessage( element, "remote" )

			});

		}

		

	},

	

	classRuleSettings: {

		required: {required: true},

		email: {email: true},

		url: {url: true},

		date: {date: true},

		dateISO: {dateISO: true},

		dateDE: {dateDE: true},

		number: {number: true},

		numberDE: {numberDE: true},

		digits: {digits: true},

		creditcard: {creditcard: true}

	},

	

	addClassRules: function(className, rules) {

		className.constructor == String ?

			this.classRuleSettings[className] = rules :

			$.extend(this.classRuleSettings, className);

	},

	

	classRules: function(element) {

		var rules = {};

		var classes = $(element).attr('class');

		classes && $.each(classes.split(' '), function() {

			if (this in $.validator.classRuleSettings) {

				$.extend(rules, $.validator.classRuleSettings[this]);

			}

		});

		return rules;

	},

	

	attributeRules: function(element) {

		var rules = {};

		var $element = $(element);

		

		for (method in $.validator.methods) {

			var value = $element.attr(method);

			if (value) {

				rules[method] = value;

			}

		}

		

		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs

		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {

			delete rules.maxlength;

		}

		

		return rules;

	},

	

	metadataRules: function(element) {

		if (!$.metadata) return {};

		

		var meta = $.data(element.form, 'validator').settings.meta;

		return meta ?

			$(element).metadata()[meta] :

			$(element).metadata();

	},

	

	staticRules: function(element) {

		var rules = {};

		var validator = $.data(element.form, 'validator');

		if (validator.settings.rules) {

			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};

		}

		return rules;

	},

	

	normalizeRules: function(rules, element) {

		// handle dependency check

		$.each(rules, function(prop, val) {

			// ignore rule when param is explicitly false, eg. required:false

			if (val === false) {

				delete rules[prop];

				return;

			}

			if (val.param || val.depends) {

				var keepRule = true;

				switch (typeof val.depends) {

					case "string":

						keepRule = !!$(val.depends, element.form).length;

						break;

					case "function":

						keepRule = val.depends.call(element, element);

						break;

				}

				if (keepRule) {

					rules[prop] = val.param !== undefined ? val.param : true;

				} else {

					delete rules[prop];

				}

			}

		});

		

		// evaluate parameters

		$.each(rules, function(rule, parameter) {

			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;

		});

		

		// clean number parameters

		$.each(['minlength', 'maxlength', 'min', 'max'], function() {

			if (rules[this]) {

				rules[this] = Number(rules[this]);

			}

		});

		$.each(['rangelength', 'range'], function() {

			if (rules[this]) {

				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];

			}

		});

		

		if ($.validator.autoCreateRanges) {

			// auto-create ranges

			if (rules.min && rules.max) {

				rules.range = [rules.min, rules.max];

				delete rules.min;

				delete rules.max;

			}

			if (rules.minlength && rules.maxlength) {

				rules.rangelength = [rules.minlength, rules.maxlength];

				delete rules.minlength;

				delete rules.maxlength;

			}

		}

		

		// To support custom messages in metadata ignore rule methods titled "messages"

		if (rules.messages) {

			delete rules.messages

		}

		

		return rules;

	},

	

	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}

	normalizeRule: function(data) {

		if( typeof data == "string" ) {

			var transformed = {};

			$.each(data.split(/\s/), function() {

				transformed[this] = true;

			});

			data = transformed;

		}

		return data;

	},

	

	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod

	addMethod: function(name, method, message) {

		$.validator.methods[name] = method;

		$.validator.messages[name] = message;

		if (method.length < 3) {

			$.validator.addClassRules(name, $.validator.normalizeRule(name));

		}

	},



	methods: {



		// http://docs.jquery.com/Plugins/Validation/Methods/required

		required: function(value, element, param) {

			// check if dependency is met

			if ( !this.depend(param, element) )

				return "dependency-mismatch";

			switch( element.nodeName.toLowerCase() ) {

			case 'select':

				var options = $("option:selected", element);

				return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);

			case 'input':

				if ( this.checkable(element) )

					return this.getLength(value, element) > 0;

			default:

				return $.trim(value).length > 0;

			}

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/remote

		remote: function(value, element, param) {

			if ( this.optional(element) )

				return "dependency-mismatch";

			

			var previous = this.previousValue(element);

			

			if (!this.settings.messages[element.name] )

				this.settings.messages[element.name] = {};

			this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;

			

			param = typeof param == "string" && {url:param} || param; 

			

			if ( previous.old !== value ) {

				previous.old = value;

				var validator = this;

				this.startRequest(element);

				var data = {};

				data[element.name] = value;

				$.ajax($.extend(true, {

					url: param,

					mode: "abort",

					port: "validate" + element.name,

					dataType: "json",

					data: data,

					success: function(response) {

						if ( response ) {

							var submitted = validator.formSubmitted;

							validator.prepareElement(element);

							validator.formSubmitted = submitted;

							validator.successList.push(element);

							validator.showErrors();

						} else {

							var errors = {};

							errors[element.name] =  response || validator.defaultMessage( element, "remote" );

							validator.showErrors(errors);

						}

						previous.valid = response;

						validator.stopRequest(element, response);

					}

				}, param));

				return "pending";

			} else if( this.pending[element.name] ) {

				return "pending";

			}

			return previous.valid;

		},



		// http://docs.jquery.com/Plugins/Validation/Methods/minlength

		minlength: function(value, element, param) {

			return this.optional(element) || this.getLength($.trim(value), element) >= param;

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength

		maxlength: function(value, element, param) {

			return this.optional(element) || this.getLength($.trim(value), element) <= param;

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength

		rangelength: function(value, element, param) {

			var length = this.getLength($.trim(value), element);

			return this.optional(element) || ( length >= param[0] && length <= param[1] );

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/min

		min: function( value, element, param ) {

			return this.optional(element) || value >= param;

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/max

		max: function( value, element, param ) {

			return this.optional(element) || value <= param;

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/range

		range: function( value, element, param ) {

			return this.optional(element) || ( value >= param[0] && value <= param[1] );

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/email

		email: function(value, element) {

			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/

			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);

		},

	

		// http://docs.jquery.com/Plugins/Validation/Methods/url

		url: function(value, element) {

			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/

			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);

		},

        

		// http://docs.jquery.com/Plugins/Validation/Methods/date

		date: function(value, element) {

			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));

		},

	

		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO

		dateISO: function(value, element) {

			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);

		},

	

		// http://docs.jquery.com/Plugins/Validation/Methods/dateDE

		dateDE: function(value, element) {

			return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);

		},

	

		// http://docs.jquery.com/Plugins/Validation/Methods/number

		number: function(value, element) {

			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);

		},

	

		// http://docs.jquery.com/Plugins/Validation/Methods/numberDE

		numberDE: function(value, element) {

			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/digits

		digits: function(value, element) {

			return this.optional(element) || /^\d+$/.test(value);

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard

		// based on http://en.wikipedia.org/wiki/Luhn

		creditcard: function(value, element) {

			if ( this.optional(element) )

				return "dependency-mismatch";

			// accept only digits and dashes

			if (/[^0-9-]+/.test(value))

				return false;

			var nCheck = 0,

				nDigit = 0,

				bEven = false;



			value = value.replace(/\D/g, "");



			for (n = value.length - 1; n >= 0; n--) {

				var cDigit = value.charAt(n);

				var nDigit = parseInt(cDigit, 10);

				if (bEven) {

					if ((nDigit *= 2) > 9)

						nDigit -= 9;

				}

				nCheck += nDigit;

				bEven = !bEven;

			}



			return (nCheck % 10) == 0;

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/accept

		accept: function(value, element, param) {

			param = typeof param == "string" ? param : "png|jpe?g|gif";

			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 

		},

		

		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo

		equalTo: function(value, element, param) {

			return value == $(param).val();

		}

		

	}

	

});



})(jQuery);



// ajax mode: abort

// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});

// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 

;(function($) {

	var ajax = $.ajax;

	var pendingRequests = {};

	$.ajax = function(settings) {

		// create settings for compatibility with ajaxSetup

		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));

		var port = settings.port;

		if (settings.mode == "abort") {

			if ( pendingRequests[port] ) {

				pendingRequests[port].abort();

			}

			return (pendingRequests[port] = ajax.apply(this, arguments));

		}

		return ajax.apply(this, arguments);

	};

})(jQuery);



// provides cross-browser focusin and focusout events

// IE has native support, in other browsers, use event caputuring (neither bubbles)



// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation

// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 



// provides triggerEvent(type: String, target: Element) to trigger delegated events

;(function($) {

	$.each({

		focus: 'focusin',

		blur: 'focusout'	

	}, function( original, fix ){

		$.event.special[fix] = {

			setup:function() {

				if ( $.browser.msie ) return false;

				this.addEventListener( original, $.event.special[fix].handler, true );

			},

			teardown:function() {

				if ( $.browser.msie ) return false;

				this.removeEventListener( original,

				$.event.special[fix].handler, true );

			},

			handler: function(e) {

				arguments[0] = $.event.fix(e);

				arguments[0].type = fix;

				return $.event.handle.apply(this, arguments);

			}

		};

	});

	$.extend($.fn, {

		delegate: function(type, delegate, handler) {

			return this.bind(type, function(event) {

				var target = $(event.target);

				if (target.is(delegate)) {

					return handler.apply(target, arguments);

				}

			});

		},

		triggerEvent: function(type, target) {

			return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);

		}

	})

})(jQuery);


