/**
 *
 *	sgm.core.js
 *	- jQuery plugins
 ---------------------------------------------------------------------------------------*/

/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);

/**
 * jQuery.LocalScroll - Animated scrolling navigation, using anchors.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/11/2009
 * @author Ariel Flesler
 * @version 1.2.7
 **/
;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('<a> </a>').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);



/**
 * jQuery.timers - Timer abstractions for jQuery
 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/10/16
 *
 * @author Blair Mitchelmore
 * @version 1.2
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times);
		});
	},
	oneTime: function(interval, label, fn) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, 1);
		});
	},
	stopTime: function(label, fn) {
		return this.each(function() {
			jQuery.timer.remove(this, label, fn);
		});
	}
});

jQuery.extend({
	timer: {
		global: [],
		guid: 1,
		dataKey: "jQuery.timer",
		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
		powers: {
			// Yeah this is major overkill...
			'ms': 1,
			'cs': 10,
			'ds': 100,
			's': 1000,
			'das': 10000,
			'hs': 100000,
			'ks': 1000000
		},
		timeParse: function(value) {
			if (value == undefined || value == null)
				return null;
			var result = this.regex.exec(jQuery.trim(value.toString()));
			if (result[2]) {
				var num = parseFloat(result[1]);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times) {
			var counter = 0;

			if (jQuery.isFunction(label)) {
				if (!times) 
					times = fn;
				fn = label;
				label = interval;
			}

			interval = jQuery.timer.timeParse(interval);

			if (typeof interval != 'number' || isNaN(interval) || interval < 0)
				return;

			if (typeof times != 'number' || isNaN(times) || times < 0) 
				times = 0;

			times = times || 0;

			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});

			if (!timers[label])
				timers[label] = {};

			fn.timerID = fn.timerID || this.guid++;

			var handler = function() {
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
			};

			handler.timerID = fn.timerID;

			if (!timers[label][fn.timerID])
				timers[label][fn.timerID] = window.setInterval(handler,interval);

			this.global.push( element );

		},
		remove: function(element, label, fn) {
			var timers = jQuery.data(element, this.dataKey), ret;

			if ( timers ) {

				if (!label) {
					for ( label in timers )
						this.remove(element, label, fn);
				} else if ( timers[label] ) {
					if ( fn ) {
						if ( fn.timerID ) {
							window.clearInterval(timers[label][fn.timerID]);
							delete timers[label][fn.timerID];
						}
					} else {
						for ( var fn in timers[label] ) {
							window.clearInterval(timers[label][fn]);
							delete timers[label][fn];
						}
					}

					for ( ret in timers[label] ) break;
					if ( !ret ) {
						ret = null;
						delete timers[label];
					}
				}

				for ( ret in timers ) break;
				if ( !ret ) 
					jQuery.removeData(element, this.dataKey);
			}
		}
	}
});

jQuery(window).bind("unload", function() {
	jQuery.each(jQuery.timer.global, function(index, item) {
		jQuery.timer.remove(item);
	});
});

/*

JQuery Curvy Corners by Mike Jolley
http://blue-anvil.com
http://code.google.com/p/jquerycurvycorners/
------------ 
Version 2.0.2 Beta 3

Original by: Terry Riegel, Cameron Cooke and Tim Hutchison
Website: http://www.curvycorners.net

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/*
Differences from offical CC:
- Boxes are not fixed size and will auto size to content
- Backgrounds aligned to bottom won't work correctly so align to top if you need to tile

Usage:
Will now autoMagically apply borders via the CSS declarations
Safari, Mozilla, and Chrome all support rounded borders via

-webkit-border-radius, and -moz-border-radius

So to make curvycorners work with any major browser simply add the following
CSS declarations and it should be good to go...

.round { 
	-webkit-border-radius: 25px;
    -moz-border-radius: 25px;
    CCborderRadius: 25px;
}

You can still use the direct syntax:

$('.myBox').corner();

Add the styles in the page itself to support Opera!

*/  
function styleit()
{
for(var t = 0; t < document.styleSheets.length; t++)
{
	var theRules = new Array();
	theRules = document.styleSheets[t].rules;

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

		var allR = theRules[i].style.CCborderRadius    || 0;
		var tR   = theRules[i].style.CCborderRadiusTR  || allR;
		var tL   = theRules[i].style.CCborderRadiusTL  || allR;
		var bR   = theRules[i].style.CCborderRadiusBR  || allR;
		var bL   = theRules[i].style.CCborderRadiusBL  || allR;

		if (allR || tR || tR || bR || bL)
		{
			var s = theRules[i].selectorText;

			var settings = {					
				tl: { radius: makeInt(tL) },
				tr: { radius: makeInt(tR) },
				bl: { radius: makeInt(bL) },
				br: { radius: makeInt(bR) },
				antiAlias: true,
				autoPad: true,
				validTags: ["div"]
			};

			$(s).corner(settings); 

		}
	}
}
}

//static class function to determine if the sheet is worth parsing
function opera_contains_border_radius(sheetnumber) {
return /border-((top|bottom)-(left|right)-)?radius/.test(document.styleSheets.item(sheetnumber).ownerNode.text);
}

function makeInt(num) {
var re = new RegExp('([0-9]*)');
var i = 0;
if(isNaN(num)) {
	var a = re.exec(num);
	if(!isNaN(parseInt(a[1]))) {
		i = a[1];
	}
}
else {
	i = num;
}	
return i;
}

(function($) { 

$(function(){
	if ($.browser.msie) {	
		styleit();
	} else if ($.browser.opera) {

  		for (t = 0; t < document.styleSheets.length; ++t) {

    		if (opera_contains_border_radius(t)) {

				var txt = document.styleSheets.item(t).ownerNode.text;
				txt = txt.replace(/\/\*(\n|\r|.)*?\*\//g, ''); // strip comments
				// this pattern extracts all border-radius-containing rulesets
				// matches will be:
				// [0] = the whole lot
				// [1] = the selector text
				// [2] = all the rule text between braces
				// [3] = top/bottom and left/right parts if present (only if webkit/CSS3)
				// [4] = top|bottom
				// [5] = left|right
				// .. but 3..5 are useless as they're only the first match.
				var pat = new RegExp("^([\\w.#][\\w.#, ]+)[\\n\\s]*\\{([^}]+border-((top|bottom)-(left|right)-)?radius[^}]*)\\}", "mg");
				var matches;
				while ((matches = pat.exec(txt)) !== null) {
					var pat2 = new RegExp("(..)border-((top|bottom)-(left|right)-)?radius:\\s*([\\d.]+)(in|em|px|ex|pt)", "g");
					var submatches;
					while ((submatches = pat2.exec(matches[2])) !== null) {
					    if (submatches[1] !== "z-") {
					    	var tL,tR,bL,bR, tLu,tRu,bLu,bRu;					    							  
							if (!submatches[3]) { // no corner specified
								tL = tR = bL = bR = parseInt(submatches[5]);
								//tLu = tRu = bLu = bRu = submatches[6];
							}
							else { // corner specified
								propname = submatches[3].charAt(0) + submatches[4].charAt(0);
								this[propname + 'R'] = parseInt(submatches[5]);
								//this[propname + 'u'] = submatches[6];
							}
							var settings = {					
								tl: { radius: tL },
								tr: { radius: tR },
								bl: { radius: bL },
								br: { radius: bR }
							};	
							$(matches[1]).corner(settings);
					    }
					}
				}
			}
			}
		}
});	

$.fn.corner = function(options) {

	var settings = {
	  tl: { radius: 8 },
	  tr: { radius: 8 },
	  bl: { radius: 8 },
	  br: { radius: 8 },
	  antiAlias: true,
	  autoPad: true,
	  validTags: ["div"] 
	};
	if ( options && typeof(options) != 'string' )
		$.extend(settings, options);

	return this.each(function() {
		if (!$(this).is('.hasCorners')) {
			applyCorners(this, settings);				
		}			
	}); 

		// Apply the corners to the passed object!
	function applyCorners(box,settings)
	{

		// Setup Globals
		var $$ 						= $(box);
		this.topContainer 			= null;
		this.bottomContainer 		= null;
		this.shell            		= null;
		this.masterCorners 			= new Array();
		this.contentDIV 				= null;

		// Get CSS of box and define vars

		// Background + box colour
		this.x_bgi 				= $$.css("backgroundImage");																// Background Image
		this.x_bgi				= (x_bgi != "none" && x_bgi!="initial") ? x_bgi : "";
		this.x_bgr 				= $$.css("backgroundRepeat");																// Background repeat
		this.x_bgposX			= strip_px($$.css("backgroundPositionX")) ? strip_px($$.css("backgroundPositionX")) : 0; 	// Background position
		this.x_bgposY			= strip_px($$.css("backgroundPositionY")) ? strip_px($$.css("backgroundPositionY")) : 0; 	// Background position
		this.x_bgc 				= format_colour($$.css("backgroundColor"));													// Background Colour

		// Dimensions + positioning
		var x_height 			= $$.css("height");		 					// Height

		if(typeof x_height == 'undefined') x_height = 'auto';

		this.x_height       	= parseInt(((x_height != "" && x_height != "auto" && x_height.indexOf("%") == -1)? x_height.substring(0, x_height.indexOf("px")) : box.offsetHeight));

		if($.browser.msie && $.browser.version==6)
		{
			this.x_width	 		= strip_px(box.offsetWidth); 
		} 
		else 
		{
			this.x_width	 		= strip_px($$.css('width')); 
		}		

		this.xp_height      	= strip_px($$.parent().css("height")) ? strip_px($$.css("height")) : 'auto';				// Parent height

		// Borders
		this.x_bw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0; 				// Border width

		// Different widths messed up borders
		this.x_bbw		     	= strip_px($$.css("borderBottomWidth")) ? strip_px($$.css("borderBottomWidth")) : 0; 		// Bottom Border width
		this.x_tbw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0; 				// Top Border width
		this.x_lbw		     	= strip_px($$.css("borderLeftWidth")) ? strip_px($$.css("borderLeftWidth")) : 0; 			// Left Border width
		this.x_rbw		     	= strip_px($$.css("borderRightWidth")) ? strip_px($$.css("borderRightWidth")) : 0; 			// Right Border width

		/*this.x_bbw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0;
		this.x_tbw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0;
		this.x_lbw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0;
		this.x_rbw		     	= strip_px($$.css("borderTopWidth")) ? strip_px($$.css("borderTopWidth")) : 0;*/


		this.x_bc		     	= format_colour($$.css("borderTopColor")); 													// Border colour
		this.x_bbc		     	= format_colour($$.css("borderBottomColor")); 												// Bottom Border colour
		this.x_tbc		     	= format_colour($$.css("borderTopColor")); 													// Top Border colour
		this.x_lbc		     	= format_colour($$.css("borderLeftColor")); 												// Left Border colour
		this.x_rbc		     	= format_colour($$.css("borderRightColor")); 												// Right Border colour
		this.borderString    	= this.x_bw + "px" + " solid " + this.x_bc;
  		this.borderStringB   	= this.x_bbw + "px" + " solid " + this.x_bbc;
  		this.borderStringR    	= this.x_rbw + "px" + " solid " + this.x_bc;
  		this.borderStringL   	= this.x_lbw + "px" + " solid " + this.x_bbc;

		// Padding
		this.x_pad		      	= strip_px($$.css("paddingTop"));															// Padding
		this.x_tpad	 			= strip_px($$.css("paddingTop"));															// Padding top
		this.x_bpad 			= strip_px($$.css("paddingBottom"));														// Padding Bottom
		this.x_lpad			 	= strip_px($$.css("paddingLeft"));															// Padding Left		
		this.x_rpad			 	= strip_px($$.css("paddingRight"));															// Padding Right
		this.topPaddingP     	= strip_px($$.parent().css("paddingTop"));													// Parent top padding
		//this.topPaddingP     	= strip_px($$.parent().css("paddingTop"));													// Parent top padding
		this.bottomPaddingP  	= strip_px($$.parent().css("paddingBottom"));												// Parent bottom padding

		// Margins
		this.x_tmargin	 		= strip_px($$.css("marginTop"));														// Margin top
		this.x_bmargin 			= strip_px($$.css("marginBottom"));														// Margin Bottom

		// Calc Radius
		this.topMaxRadius = Math.max(settings.tl ? settings.tl.radius : 0, settings.tr ? settings.tr.radius : 0);
		this.botMaxRadius = Math.max(settings.bl ? settings.bl.radius : 0, settings.br ? settings.br.radius : 0);

		// Add styles and class		
		$$.addClass('hasCorners').css({
			"padding":				"0", 
			"border":				"none",
			"backgroundColor":		"transparent", 
			"backgroundImage":		"none", 
			'overflow':				"visible"
		});

		if(box.style.position != "absolute") $$.css("position","relative");

   		$$.attr("id","ccoriginaldiv");

		// Ok we add an inner div to actually put things into this will allow us to keep the height			
		var newMainContainer = document.createElement("div");

		$(newMainContainer).css({"padding" : "0", width: '100%' }).attr('id','ccshell');			

   		//this.shell = $$.append(newMainContainer);
   		this.shell = newMainContainer;

  		//this.x_width = strip_px($(this.shell).css('width'));

		/*
		Create top and bottom containers.
		These will be used as a parent for the corners and bars.
		*/
		for(var t = 0; t < 2; t++)
		{
			switch(t)
			{
				// Top
				case 0:

					// Only build top bar if a top corner is to be draw
					if(settings.tl || settings.tr)
					{
						var newMainContainer = document.createElement("div");

						$(newMainContainer).css({
							width: '100%',
							"font-size":		"1px", 
							overflow:			"hidden", 
							position:			"absolute", 
							height:				topMaxRadius + "px",
							top:				0 - topMaxRadius + "px",
							"marginLeft" :			- parseInt( this.x_lbw + this.x_lpad) + "px",
							"marginRight" :			- parseInt( this.x_rbw + this.x_rpad) + "px"
						}).attr('id','cctopcontainer');

						if($.browser.msie && $.browser.version==6) {
							$(newMainContainer).css({   	
								"paddingLeft" :			Math.abs(parseInt( this.x_lbw + this.x_lpad)) + "px",
								"paddingRight" :		Math.abs(parseInt( this.x_rbw + this.x_rpad)) + "px"
					        });
				        }

						this.topContainer = this.shell.appendChild(newMainContainer);

					}
				break;

				// Bottom
				case 1:

					// Only build bottom bar if a bottom corner is to be draw
					if(settings.bl || settings.br)
					{							
						var newMainContainer = document.createElement("div");

						$(newMainContainer).css({ 
							width: '100%',
							"font-size":		"1px", 
							"overflow":			"hidden", 
							"position":			"absolute", 
							height:				botMaxRadius + "px",
							bottom:				0 - botMaxRadius  + "px",
							"marginLeft" :			- parseInt( this.x_lbw + this.x_lpad) + "px",
							"marginRight" :			- parseInt( this.x_rbw + this.x_rpad) + "px"
						}).attr('id','ccbottomcontainer');

						if($.browser.msie && $.browser.version==6) {
							$(newMainContainer).css({   	
								"paddingLeft" :			Math.abs(parseInt( this.x_lbw + this.x_lpad)) + "px",
								"paddingRight" :		Math.abs(parseInt( this.x_rbw + this.x_rpad)) + "px"
					        });
				        }

						this.bottomContainer = this.shell.appendChild(newMainContainer);	
					}
				break;
			}
		}


		// Create array of available corners
		var corners = ["tr", "tl", "br", "bl"];
		/*
		Loop for each corner
		*/
		for(var i in corners)
		{
			if(i > -1 < 4)
			{
				// Get current corner type from array
				var cc = corners[i];
				// Has the user requested the currentCorner be round?
				// Code to apply correct color to top or bottom
				if(cc == "tr" || cc == "tl")
				{
					var bwidth=this.x_bw;
					var bcolor=this.x_bc;
				} else {
					var bwidth=this.x_bbw;
					var bcolor=this.x_bbc;
				}

				// Yes, we need to create a new corner
				var newCorner = document.createElement("div");

				$(newCorner).css({
					position:"absolute",
					"font-size":"1px", 
					overflow:"hidden"
				}).height(settings[cc].radius + "px").width(settings[cc].radius + "px");

				// THE FOLLOWING BLOCK OF CODE CREATES A ROUNDED CORNER
				// ---------------------------------------------------- TOP
				// Get border radius
				var borderRadius = parseInt(settings[cc].radius - bwidth);
				// Cycle the x-axis
				for(var intx = 0, j = settings[cc].radius; intx < j; intx++)
				{
                  // Calculate the value of y1 which identifies the pixels inside the border
                  if((intx +1) >= borderRadius)
                    var y1 = -1;
                  else
                    var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1);
                  // Only calculate y2 and y3 if there is a border defined
                  if(borderRadius != j)
                  {
                      if((intx) >= borderRadius)
                        var y2 = -1;
                      else
                        var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2)));
                       if((intx+1) >= j)
                        var y3 = -1;
                       else
                        var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);
                  }
                  // Calculate y4
                  if((intx) >= j)
                    var y4 = -1;
                  else
                    var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2)));
                  // Draw bar on inside of the border with foreground colour

                  if(y1 > -1) drawPixel(intx, 0, this.x_bgc, 100, (y1+1), newCorner, -1, settings[cc].radius, 0, this.x_bgi, this.x_width, this.x_height, this.x_bw, this.x_bgr);
                  // Only draw border/foreground antialiased pixels and border if there is a border defined
                  if(borderRadius != j)
                  {
                      // Cycle the y-axis
                      for(var inty = (y1 + 1); inty < y2; inty++)
                      {
                          // Draw anti-alias pixels
                          if(settings.antiAlias)
                          {
                              // For each of the pixels that need anti aliasing between the foreground and border colour draw single pixel divs
                              if(this.x_bgi != "")
                              {
									var borderFract = (pixelFraction(intx, inty, borderRadius) * 100);
									if(borderFract < 30)
									{
										drawPixel(intx, inty, bcolor, 100, 1, newCorner, 0, settings[cc].radius, 0, this.x_bgi, this.x_width, this.x_height, bwidth, this.x_bgr);
									}
									else
									{
										drawPixel(intx, inty, bcolor, 100, 1, newCorner, -1, settings[cc].radius, 0, this.x_bgi, this.x_width, this.x_height, bwidth, this.x_bgr);
                              		}
                              	}
                              	else
                              	{
                                  	var pixelcolour = BlendColour(this.x_bgc, bcolor, pixelFraction(intx, inty, borderRadius));
                                 	drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, settings[cc].radius, 0, this.x_bgi, this.x_width, this.x_height, bwidth, this.x_bgr);
                              	}
                          }
                      }
                      // Draw bar for the border
                      if(settings.antiAlias)
                      {
                          if(y3 >= y2)
                          {
                             if (y2 == -1) y2 = 0;
                             drawPixel(intx, y2, bcolor, 100, (y3 - y2 + 1), newCorner, 0, 0, 1, this.x_bgi, this.x_width, this.x_height, bwidth, this.x_bgr);
                          }
                      }
                      else
                      {
                          if(y3 >= y1)
                          {
                              drawPixel(intx, (y1 + 1), bcolor, 100, (y3 - y1), newCorner, 0, 0, 1, this.x_bgi, this.x_width, this.x_height, bwidth, this.x_bgr);
                          }
                      }
                      // Set the colour for the outside curve
                      var outsideColour = bcolor;
                  }
                  else
                  {
                      // Set the colour for the outside curve
                      var outsideColour = this.x_bgc;
                      var y3 = y1;
                  }
                  // Draw aa pixels?
                  if(settings.antiAlias)
                  {
                      // Cycle the y-axis and draw the anti aliased pixels on the outside of the curve
                      for(var inty = (y3 + 1); inty < y4; inty++)
                      {
                          // For each of the pixels that need anti aliasing between the foreground/border colour & background draw single pixel divs
                          drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((bwidth > 0)? 0 : -1), settings[cc].radius, 0, this.x_bgi, this.x_width, this.x_height, bwidth);
                      }
                  }
              }
              // END OF CORNER CREATION
              // ---------------------------------------------------- END

              // We now need to store the current corner in the masterConers array
              masterCorners[settings[cc].radius] = $(newCorner).clone();

              /*
              Now we have a new corner we need to reposition all the pixels unless
              the current corner is the bottom right.
              */
              // Loop through all children (pixel bars)
              for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
              {
                  // Get current pixel bar
                  var pixelBar = newCorner.childNodes[t];

                  // Get current top and left properties
                  var pixelBarTop    = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px")));
                  var pixelBarLeft   = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px")));
                  var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px")));

                  // Reposition pixels
                  if(cc == "tl" || cc == "bl"){
                      pixelBar.style.left = settings[cc].radius -pixelBarLeft -1 + "px"; // Left
                  }
                  if(cc == "tr" || cc == "tl"){
                      pixelBar.style.top =  settings[cc].radius -pixelBarHeight -pixelBarTop + "px"; // Top
                  }
                  pixelBar.style.backgroundRepeat = this.x_bgr;

                  switch(cc)
                  {
                      case "tr":

								if($.browser.msie && $.browser.version==6) var offset = this.x_lpad + this.x_rpad + this.x_lbw + this.x_rbw;
								else var offset = 0;

                            pixelBar.style.backgroundPosition  = parseInt( this.x_bgposX - Math.abs( this.x_rbw - this.x_lbw + (this.x_width - settings[cc].radius + this.x_rbw) + pixelBarLeft) - settings.bl.radius - this.x_bw - settings.br.radius - this.x_bw) + offset + "px " + parseInt( this.x_bgposY - Math.abs(settings[cc].radius -pixelBarHeight -pixelBarTop - this.x_bw)) + "px";

                          break;
                      case "tl":
                          pixelBar.style.backgroundPosition = parseInt( this.x_bgposX - Math.abs((settings[cc].radius -pixelBarLeft -1)  - this.x_lbw)) + "px " + parseInt( this.x_bgposY - Math.abs(settings[cc].radius -pixelBarHeight -pixelBarTop - this.x_bw)) + "px";
                          break;
                      case "bl":

                              pixelBar.style.backgroundPosition = parseInt( this.x_bgposX - Math.abs((settings[cc].radius -pixelBarLeft -1) - this.x_lbw )) + "px " + parseInt( this.x_bgposY - Math.abs(( this.x_height + (this.x_bw+this.x_tpad+this.x_bpad) - settings[cc].radius + pixelBarTop))) + "px";

                          break;
                      case "br":
							  // Added - settings.bl.radius - this.x_bw - settings.br.radius - this.x_bw to this and tr to offset background image due to neg margins.
							  if($.browser.msie && $.browser.version==6) var offset = this.x_lpad + this.x_rpad + this.x_lbw + this.x_rbw;
									else var offset = 0;

                              pixelBar.style.backgroundPosition = parseInt( this.x_bgposX - Math.abs( this.x_rbw - this.x_lbw + (this.x_width - settings[cc].radius + this.x_rbw) + pixelBarLeft) - settings.bl.radius - this.x_bw - settings.br.radius - this.x_bw) + offset + "px " + parseInt( this.x_bgposY - Math.abs(( this.x_height + (this.x_bw+this.x_tpad+this.x_bpad) - settings[cc].radius + pixelBarTop))) + "px";

                          break;
                  }
              }

              // Position the container
              switch(cc)
              {


                  case "tl":
                    if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
                    if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
                    if(this.topContainer) temp= this.topContainer.appendChild(newCorner);
					$(temp).attr("id","cctl");


                    break;
                  case "tr":
                    if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
                    if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
                    if(this.topContainer) temp= this.topContainer.appendChild(newCorner);
					$(temp).attr("id","cctr");

                    break;
                  case "bl":
                    if(newCorner.style.position == "absolute") newCorner.style.bottom  = "0px";
                    if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
					if(this.bottomContainer) temp= this.bottomContainer.appendChild(newCorner);
					$(temp).attr("id","ccbl");

                    break;
                  case "br":
                    if(newCorner.style.position == "absolute") newCorner.style.bottom   = "0px";
                    if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
					if(this.bottomContainer) temp= this.bottomContainer.appendChild(newCorner);
					$(temp).attr("id","ccbr");

                    break;
              }

          }
      }



      /*
      The last thing to do is draw the rest of the filler DIVs.
      We only need to create a filler DIVs when two corners have
      diffrent radiuses in either the top or bottom container.
      */

      // Find out which corner has the bigger radius and get the difference amount
      var radiusDiff = new Array();
      radiusDiff["t"] = Math.abs(settings.tl.radius - settings.tr.radius);
      radiusDiff["b"] = Math.abs(settings.bl.radius - settings.br.radius);

      for(z in radiusDiff)
      {
          // FIX for prototype lib
          if(z == "t" || z == "b")
          {
              if(radiusDiff[z])
              {
                  // Get the type of corner that is the smaller one
                  var smallerCornerType = ((settings[z + "l"].radius < settings[z + "r"].radius)? z +"l" : z +"r");

                  // First we need to create a DIV for the space under the smaller corner
                  var newFiller = document.createElement("DIV");
                  newFiller.style.height = radiusDiff[z] + "px";
                  newFiller.style.width  =  settings[smallerCornerType].radius + "px";
                  newFiller.style.position = "absolute";
                  newFiller.style.fontSize = "1px";
                  newFiller.style.overflow = "hidden";
                  newFiller.style.backgroundColor = this.x_bgc;
                  //newFiller.style.backgroundColor = get_random_color();

                  // Position filler
                  switch(smallerCornerType)
                  {
                      case "tl":
                          newFiller.style.bottom = "0px";
                          newFiller.style.left   = "0px";
                          newFiller.style.borderLeft = this.borderString;
                          temp=this.topContainer.appendChild(newFiller);
temp.id="cctlfiller";

                          break;

                      case "tr":
                          newFiller.style.bottom = "0px";
                          newFiller.style.right  = "0px";
                          newFiller.style.borderRight = this.borderString;
                          temp=this.topContainer.appendChild(newFiller);
temp.id="cctrfiller";

                          break;

                      case "bl":
                          newFiller.style.top    = "0px";
                          newFiller.style.left   = "0px";
                          newFiller.style.borderLeft = this.borderStringB;
                          temp=this.bottomContainer.appendChild(newFiller);
						temp.id="ccblfiller";

                          break;

                      case "br":
                          newFiller.style.top    = "0px";
                          newFiller.style.right  = "0px";
                          newFiller.style.borderRight = this.borderStringB;
                          temp=this.bottomContainer.appendChild(newFiller);
							temp.id="ccbrfiller";

                          break;
                  }
              }


              // Create the bar to fill the gap between each corner horizontally
              var newFillerBar = document.createElement("div");
              newFillerBar.style.position = "relative";
              newFillerBar.style.fontSize = "1px";
              newFillerBar.style.overflow = "hidden";
              newFillerBar.style.backgroundColor = this.x_bgc;
              newFillerBar.style.backgroundImage = this.x_bgi;
              newFillerBar.style.backgroundRepeat= this.x_bgr;


              switch(z)
              {
                  case "t":
                      // Top Bar
                      if(this.topContainer)
                      {
                          // Edit by Asger Hallas: Check if settings.xx.radius is not false
                          if(settings.tl.radius && settings.tr.radius)
                          {
                              newFillerBar.style.height      = 100 + topMaxRadius - this.x_tbw + "px";
                              newFillerBar.style.marginLeft  = settings.tl.radius - this.x_lbw + this.x_rbw + "px";
                              newFillerBar.style.marginRight = settings.tr.radius - this.x_lbw + this.x_rbw + "px";
                              newFillerBar.style.borderTop   = this.borderString;                                 

                              if(this.x_bgi != "")
                                newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX - (topMaxRadius - this.x_lbw )) + "px " + parseInt( this.x_bgposY ) + "px";
                                //newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX - (topMaxRadius - this.x_lbw)) + "px " + parseInt( this.x_bgposY ) + "px";

								if($.browser.msie && $.browser.version==6) {
									$(newFillerBar).css({   	
										"marginLeft" :		- parseInt( this.x_lbw + this.x_lpad - settings.tl.radius ) + "px",
										"marginRight" :		- parseInt( this.x_rbw + this.x_rpad - settings.tr.radius ) + "px"
									});
									 if(this.x_bgi != "")
                                		newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX + this.x_lbw - (topMaxRadius )) + "px " + parseInt( this.x_bgposY ) + "px";
				       			}


                              temp=this.topContainer.appendChild(newFillerBar);
							  $(temp).attr("id","cctopmiddlefiller");

                              // Repos the boxes background image
                              $(this.shell).css("backgroundPosition", parseInt( this.x_bgposX ) + "px " + parseInt( this.x_bgposY - (topMaxRadius - this.x_lbw)) + "px");
                          }
                      }
                      break;
                  case "b":
                      if(this.bottomContainer)
                      {
                          // Edit by Asger Hallas: Check if settings.xx.radius is not false
                          if(settings.bl.radius && settings.br.radius)
                          {
                              // Bottom Bar
                              newFillerBar.style.height     = botMaxRadius - this.x_bbw + "px";
                              newFillerBar.style.marginLeft   = settings.bl.radius - this.x_lbw + this.x_rbw + "px";
                              newFillerBar.style.marginRight  = settings.br.radius - this.x_lbw + this.x_rbw + "px";
                              newFillerBar.style.borderBottom = this.borderStringB;
                              if(this.x_bgi != "")
                                newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX - (botMaxRadius - this.x_lbw )) + "px " + parseInt( this.x_bgposY - (this.x_height + this.x_tpad + this.x_bbw + this.x_bpad - botMaxRadius )) + "px";
                                //newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX - (botMaxRadius  - this.x_lbw )) + "px " + parseInt( this.x_bgposY - (this.x_height + this.x_tpad + this.x_bw + this.x_bpad - botMaxRadius )) + "px";

                              if($.browser.msie && $.browser.version==6) {
									$(newFillerBar).css({   	
										"marginLeft" :		- parseInt( this.x_lbw + this.x_lpad - settings.bl.radius ) + "px",
										"marginRight" :		- parseInt( this.x_rbw + this.x_rpad - settings.br.radius ) + "px"
									});

									if(this.x_bgi != "")
                                		newFillerBar.style.backgroundPosition  = parseInt( this.x_bgposX - (botMaxRadius - this.x_lbw)) + "px " + parseInt( this.x_bgposY - (this.x_height + this.x_tpad + this.x_bbw + this.x_bpad - botMaxRadius )) + "px";
				       			}

                              temp=this.bottomContainer.appendChild(newFillerBar);
$(temp).attr("id","ccbottommiddlefiller");

                          }
                      }
                      break;
              }
          }
      }


      // Create content container
      var contentContainer = document.createElement("div");
      var pd = 0;
      // Set contentContainer's properties
    //  contentContainer.style.position = "absolute";
      contentContainer.className      = "autoPadDiv";
      // Get padding amounts
      var topPadding = Math.abs( this.x_bw  + this.x_pad);
      var botPadding = Math.abs( this.x_bbw + this.x_bpad);

      // Apply top padding
      if(topMaxRadius < this.boxPadding)
        {
         contentContainer.style.paddingTop = Math.abs(parseInt( pd + topPadding)) + "px";
        } 
        else
        {
        contentContainer.style.paddingTop = "0";
      }

      // Apply Bottom padding
      if(botMaxRadius < this.x_pad)
        {contentContainer.style.paddingBottom = Math.abs(parseInt(botPadding - botMaxRadius)) + "px";} else
        {contentContainer.style.paddingBottom = "0";}

      // Content container must fill vertically to show the border
      $(contentContainer).css({   	
		"marginLeft" :			- parseInt( this.x_lbw + this.x_lpad) + "px",
		"marginRight" :			- parseInt( this.x_rbw + this.x_rpad) + "px",			
		"marginTop" :			"-" + Math.abs(parseInt( this.x_tbw + (this.x_tpad - topMaxRadius))) + "px",
		//"marginTop" :			"-10px", // *** ICO *** //
		
		"marginBottom" :		"-" + Math.abs(parseInt( this.x_bbw + (this.x_bpad - botMaxRadius))) + "px",
		"border-left" :				this.borderStringL,
		"border-right" :			this.borderStringR,
		"border-top" :				this.borderString,
		"border-bottom" :			this.borderStringB,
		"borderTopWidth" :		"0",
		"borderBottomWidth" :	"0",
		"height" : 				"100%",
		"width" : "100%",
		"paddingLeft" :			Math.abs(parseInt( this.x_lpad)) + "px",
		"paddingRight" :		Math.abs(parseInt( this.x_rpad)) + "px",
		"paddingTop" :			Math.abs(parseInt( this.x_tbw + (this.x_tpad - topMaxRadius))) + "px",
		"paddingBottom" :   	Math.abs(parseInt( this.x_bbw + (this.x_bpad - botMaxRadius))) + "px"
      });


      // Origional container has background image
      $$.css({            
      	"paddingLeft" :			Math.abs(parseInt( this.x_lbw + this.x_lpad)) + "px",
		"paddingRight" :		Math.abs(parseInt( this.x_rbw + this.x_rpad)) + "px",
		"paddingTop" :			Math.abs(parseInt( this.x_tbw + (this.x_tpad - topMaxRadius))) + "px",
		"paddingBottom" :      	Math.abs(parseInt( this.x_bbw + (this.x_bpad - botMaxRadius))) + "px",
		"backgroundColor" : 	this.x_bgc,
		"backgroundImage" :		this.x_bgi,
		"backgroundPosition" : 	this.x_bw + 'px -' + Math.abs(parseInt(topMaxRadius - this.x_bw )) + "px",
		'margin-top':			0, 
	  	'margin-bottom':		0
      });

      //'margin-top':			parseInt(this.x_tmargin + topMaxRadius) + "px", 
	  //'margin-bottom':		parseInt(this.x_bmargin + botMaxRadius) + "px"

      // IE does not like an empty box; without this it won't show the contentContainer
      if ($$.html() == "") $$.html('&nbsp;');

      // Append contentContainer
      $$.wrapInner(contentContainer);          
      $$.prepend(this.shell);

      // Wrapper to make margins work correctly
      var wrapper = document.createElement("div");

      $(wrapper).css({            
		'margin-top':			parseInt(this.x_tmargin) + "px", 
		'margin-bottom':		parseInt(this.x_bmargin) + "px",
		'padding-top':			topMaxRadius + "px", 
		'padding-bottom':		botMaxRadius + "px",
		'overflow': 'hidden'
      }).addClass('ccwrapper');

      $$.wrap(wrapper);

      // Because of this method of doing the corners we have magins above and below; the following prevents margin collapsing.
      $$.after('<div class="clear" style="height:0;line-height:0px;">&nbsp;</div>');
  }		

	/*
	This function draws the pixels
	*/	
	function drawPixel( intx, inty, colour, transAmount, height, newCorner, image, cornerRadius, isBorder, bgImage, x_width, x_height, x_bw, repeat ) {

		//var $$ = $(box);			

	    var pixel = document.createElement("div");

	    $(pixel).css({	
	    	"height" :			height, 
	    	"width" :			"1px", 
	    	"position" :		"absolute", 
	    	"font-size" :		"1px", 
	    	"overflow" :		"hidden",
	    	"top" :				inty + "px",
	    	"left" :			intx + "px",
	    	"background-color" :colour
	    });

	    // Max Top Radius
	    var topMaxRadius = Math.max(settings.tl ? settings.tl.radius : 0, settings.tr ? settings.tr.radius : 0);

	    // Dont apply background image to border pixels
		if(image == -1 && bgImage !="")
		{
			$(pixel).css({
				"background-position":"-" + Math.abs(x_width - (cornerRadius - intx) + x_bw) + "px -" + Math.abs((x_height + topMaxRadius + inty) -x_bw) + "px",
				"background-image":bgImage,
				"background-repeat":repeat					 
			});
		}
		else
		{
			if (!isBorder) $(pixel).addClass('hasBackgroundColor');
		}		    
	    if (transAmount != 100)
	    	$(pixel).css({opacity: (transAmount/100) });

	    newCorner.appendChild(pixel);
	};		


	// Utilities
	function BlendColour(Col1, Col2, Col1Fraction) 
	{

		var red1 = parseInt(Col1.substr(1,2),16);
		var green1 = parseInt(Col1.substr(3,2),16);
		var blue1 = parseInt(Col1.substr(5,2),16);
		var red2 = parseInt(Col2.substr(1,2),16);
		var green2 = parseInt(Col2.substr(3,2),16);
		var blue2 = parseInt(Col2.substr(5,2),16);

		if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1;

		var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction)));
		if(endRed > 255) endRed = 255;
		if(endRed < 0) endRed = 0;

		var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction)));
		if(endGreen > 255) endGreen = 255;
		if(endGreen < 0) endGreen = 0;

		var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction)));
		if(endBlue > 255) endBlue = 255;
		if(endBlue < 0) endBlue = 0;

		return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);

	}

	function IntToHex(strNum) 
	{			
		rem = strNum % 16;
		base = Math.floor(strNum / 16);

		baseS = MakeHex(base);
		remS = MakeHex(rem);

		return baseS + '' + remS;
	}

	function MakeHex(x)
	{
	  if((x >= 0) && (x <= 9))
	  {
	      return x;
	  }
	  else
	  {
	      switch(x)
	      {
	          case 10: return "A";
	          case 11: return "B";
	          case 12: return "C";
	          case 13: return "D";
	          case 14: return "E";
	          case 15: return "F";
	      }
	  }
	}

	/*
	For a pixel cut by the line determines the fraction of the pixel on the 'inside' of the
	line.  Returns a number between 0 and 1
	*/
	function pixelFraction(x, y, r)
	{
		var pixelfraction = 0;

		/*
		determine the co-ordinates of the two points on the perimeter of the pixel that the
		circle crosses
		*/
		var xvalues = new Array(1);
		var yvalues = new Array(1);
		var point = 0;
		var whatsides = "";

		// x + 0 = Left
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2)));

		if ((intersect >= y) && (intersect < (y+1)))
		{
			whatsides = "Left";
			xvalues[point] = 0;
			yvalues[point] = intersect - y;
			point =  point + 1;
		}
		// y + 1 = Top
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2)));

		if ((intersect >= x) && (intersect < (x+1)))
		{
			whatsides = whatsides + "Top";
			xvalues[point] = intersect - x;
			yvalues[point] = 1;
			point = point + 1;
		}
		// x + 1 = Right
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2)));

		if ((intersect >= y) && (intersect < (y+1)))
		{
			whatsides = whatsides + "Right";
			xvalues[point] = 1;
			yvalues[point] = intersect - y;
			point =  point + 1;
		}
		// y + 0 = Bottom
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2)));

		if ((intersect >= x) && (intersect < (x+1)))
		{
			whatsides = whatsides + "Bottom";
			xvalues[point] = intersect - x;
			yvalues[point] = 0;
		}

		/*
		depending on which sides of the perimeter of the pixel the circle crosses calculate the
		fraction of the pixel inside the circle
		*/
		switch (whatsides)
		{
		      case "LeftRight":
		      pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2);
		      break;

		      case "TopRight":
		      pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2);
		      break;

		      case "TopBottom":
		      pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2);
		      break;

		      case "LeftBottom":
		      pixelfraction = (yvalues[0]*xvalues[1])/2;
		      break;

		      default:
		      pixelfraction = 1;
		}

		return pixelfraction;
	}


	// This function converts CSS rgb(x, x, x) to hexadecimal
	function rgb2Hex(rgbColour)
	{
		try{

			// Get array of RGB values
			var rgbArray = rgb2Array(rgbColour);

			// Get RGB values
			var red   = parseInt(rgbArray[0]);
			var green = parseInt(rgbArray[1]);
			var blue  = parseInt(rgbArray[2]);

			// Build hex colour code
			var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);
		}
		catch(e){			
			alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");
		}

		return hexColour;
	}

	// Returns an array of rbg values
	function rgb2Array(rgbColour)
	{
		// Remove rgb()
		var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")"));

		// Split RGB into array
		var rgbArray = rgbValues.split(", ");

		return rgbArray;
	}	

	// Formats colours
	function format_colour(colour)
	{
		var returnColour = "#ffffff";

		// Make sure colour is set and not transparent
		if(colour != "" && colour != "transparent")
		{
			// RGB Value?
			if(colour.substr(0, 3) == "rgb" && colour.substr(0, 4) != "rgba")
			{
			  // Get HEX aquiv.
			  returnColour = rgb2Hex(colour);
			}
			else if(colour.length == 4)
			{
			  // 3 chr colour code add remainder
			  returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);
			}
			else
			{
			  // Normal valid hex colour
			  returnColour = colour;
			}
		}

		return returnColour;
	}

	// Removes 'px' from string
	function strip_px(value) 
	{
		if (typeof(value)!='string') return value;
		return parseInt((( value != "auto" && value.indexOf("%") == -1 && value != "" && value.indexOf("px") !== -1)? Math.round(value.slice(0, value.indexOf("px"))) : 0))
	}

};
})(jQuery);

/*
 * jQuery Cycle Lite Plugin
 * http://malsup.com/jquery/cycle/lite/
 * Copyright (c) 2008 M. Alsup
 * Version: 1.0 (06/08/2008)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Requires: jQuery v1.2.3 or later
 */
;(function($) {

var ver = 'Lite-1.0';

$.fn.cycle = function(options) {
    return this.each(function() {
        options = options || {};
        
        if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
        this.cycleTimeout = 0;
        this.cyclePause = 0;
        
        var $cont = $(this);
        var $slides = options.slideExpr ? $(options.slideExpr, this) : $cont.children();
        var els = $slides.get();
        if (els.length < 2) {
            if (window.console && window.console.log)
                window.console.log('terminating; too few slides: ' + els.length);
            return; // don't bother
        }

        // support metadata plugin (v1.0 and v2.0)
        var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
            
        opts.before = opts.before ? [opts.before] : [];
        opts.after = opts.after ? [opts.after] : [];
        opts.after.unshift(function(){ opts.busy=0; });
            
        // allow shorthand overrides of width, height and timeout
        var cls = this.className;
        opts.width = parseInt((cls.match(/w:(\d+)/)||[])[1]) || opts.width;
        opts.height = parseInt((cls.match(/h:(\d+)/)||[])[1]) || opts.height;
        opts.timeout = parseInt((cls.match(/t:(\d+)/)||[])[1]) || opts.timeout;

        if ($cont.css('position') == 'static') 
            $cont.css('position', 'relative');
        if (opts.width) 
            $cont.width(opts.width);
        if (opts.height && opts.height != 'auto') 
            $cont.height(opts.height);

        var first = 0;
        $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) { 
            $(this).css('z-index', els.length-i) 
        });
        
        $(els[first]).css('opacity',1).show(); // opacity bit needed to handle reinit case
        if ($.browser.msie) els[first].style.removeAttribute('filter');

        if (opts.fit && opts.width) 
            $slides.width(opts.width);
        if (opts.fit && opts.height && opts.height != 'auto') 
            $slides.height(opts.height);
        if (opts.pause) 
            $cont.hover(function(){this.cyclePause=1;}, function(){this.cyclePause=0;});

        $.fn.cycle.transitions.fade($cont, $slides, opts);
        
        $slides.each(function() {
            var $el = $(this);
            this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
            this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();
        });

        $slides.not(':eq('+first+')').css({opacity:0});
        if (opts.cssFirst)
            $($slides[first]).css(opts.cssFirst);

        if (opts.timeout) {
            // ensure that timeout and speed settings are sane
            if (opts.speed.constructor == String)
                opts.speed = {slow: 600, fast: 200}[opts.speed] || 400;
            if (!opts.sync)
                opts.speed = opts.speed / 2;
            while((opts.timeout - opts.speed) < 250)
                opts.timeout += opts.speed;
        }
        opts.speedIn = opts.speed;
        opts.speedOut = opts.speed;

 		opts.slideCount = els.length;
        opts.currSlide = first;
        opts.nextSlide = 1;

        // fire artificial events
        var e0 = $slides[first];
        if (opts.before.length)
            opts.before[0].apply(e0, [e0, e0, opts, true]);
        if (opts.after.length > 1)
            opts.after[1].apply(e0, [e0, e0, opts, true]);
        
        if (opts.click && !opts.next)
            opts.next = opts.click;
        if (opts.next)
            $(opts.next).bind('click', function(){return advance(els,opts,opts.rev?-1:1)});
        if (opts.prev)
            $(opts.prev).bind('click', function(){return advance(els,opts,opts.rev?1:-1)});

        if (opts.timeout)
            this.cycleTimeout = setTimeout(function() {
                go(els,opts,0,!opts.rev)
            }, opts.timeout + (opts.delay||0));
    });
};

function go(els, opts, manual, fwd) {
    if (opts.busy) return;
    var p = els[0].parentNode, curr = els[opts.currSlide], next = els[opts.nextSlide];
    if (p.cycleTimeout === 0 && !manual) 
        return;

    if (manual || !p.cyclePause) {
        if (opts.before.length)
            $.each(opts.before, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        var after = function() {
            if ($.browser.msie)
                this.style.removeAttribute('filter');
            $.each(opts.after, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        };

        if (opts.nextSlide != opts.currSlide) {
            opts.busy = 1;
            $.fn.cycle.custom(curr, next, opts, after);
        }
        var roll = (opts.nextSlide + 1) == els.length;
        opts.nextSlide = roll ? 0 : opts.nextSlide+1;
        opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
    }
    if (opts.timeout)
        p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev) }, opts.timeout);
};

// advance slide forward or back
function advance(els, opts, val) {
    var p = els[0].parentNode, timeout = p.cycleTimeout;
    if (timeout) {
        clearTimeout(timeout);
        p.cycleTimeout = 0;
    }
    opts.nextSlide = opts.currSlide + val;
    if (opts.nextSlide < 0) {
        opts.nextSlide = els.length - 1;
    }
    else if (opts.nextSlide >= els.length) {
        opts.nextSlide = 0;
    }
    go(els, opts, 1, val>=0);
    return false;
};

$.fn.cycle.custom = function(curr, next, opts, cb) {
    var $l = $(curr), $n = $(next);
    $n.css({opacity:0});
    var fn = function() {$n.animate({opacity:1}, opts.speedIn, opts.easeIn, cb)};
    $l.animate({opacity:0}, opts.speedOut, opts.easeOut, function() {
        $l.css({display:'none'});
        if (!opts.sync) fn();
    });
    if (opts.sync) fn();
};

$.fn.cycle.transitions = {
    fade: function($cont, $slides, opts) {
        $slides.not(':eq(0)').css('opacity',0);
        opts.before.push(function() { $(this).show() });
    }
};

$.fn.cycle.ver = function() { return ver; };

// @see: http://malsup.com/jquery/cycle/lite/
$.fn.cycle.defaults = {
    timeout:       4000, 
    speed:         1000, 
    next:          null, 
    prev:          null, 
    before:        null, 
    after:         null, 
    height:       'auto',
    sync:          1,    
    fit:           0,    
    pause:         0,    
    delay:         0,    
    slideExpr:     null  
};

})(jQuery);

/*
 * jParse (Beta) v0.1
 * jparse.kylerush.net
 *
 * Copyright (c) 2009 Kyle Rush
 * Licensed under the MIT license.
 * http://creativecommons.org/licenses/MIT/
 *
 * Date: Wednesday, 7 Oct 2009
 */
(function($){$.fn.extend({jParse:function(l){var m={ajaxOpts:{dataType:($.browser.msie)?"text":"xml",contentType:'text/xml'},parentElement:'item',elementTag:['title','link','description'],output:'<div><h2><a href="jpet1">jpet0</a></h2><p>jpet2</p></div>'};settings=$.extend(true,m,l);if(settings.precallback!==undefined){runPreFunc=eval(settings.precallback)}var p=$(this);var q=/\:/;settings.ajaxOpts.success=function(b){var c;if(typeof b=="string"){c=new ActiveXObject("Microsoft.XMLDOM");c.async=false;c.loadXML(b)}else{c=b}var o=settings;var d=$(c).find(o.parentElement);var e='';var f=0;function nodeChecker(a){if(q.test(a)===true){elemTagName='[nodeName='+a+']'}else{elemTagName=a}}for(var i=0;i<d.length;i++){if(f>=settings.limit){$(p).append(e);if(settings.callback!==undefined){runPostFunc=eval(settings.callback)}return false}var g=o.output;var h=false;for(var n=0;n<o.elementTag.length;n++){var j=new RegExp('jpet'+[n]);if(typeof(o.elementTag[n])=='string'){nodeChecker(o.elementTag[n]);elemTagValue=$(d[i]).find(elemTagName).text();elemTagValue=elemTagValue.replace(/^\[CDATA\[/,'').replace(/\]\]$/,'')}else{nodeChecker(o.elementTag[n].elem);if(o.elementTag[n].attr===undefined){elemTagValue=$(d[i]).find(elemTagName).text()}else{elemTagValue=$(d[i]).find(elemTagName).attr(o.elementTag[n].attr)}if(o.elementTag[n].exclude!==undefined){var k=new RegExp(o.elementTag[n].exclude);if(k.test(elemTagValue)===true){h=true}}}g=g.replace(j,elemTagValue)}if(h!==true){e+=g;f++}}$(p).append(e);if(settings.callback!==undefined){runPostFunc=eval(settings.callback)}};return this.each(function(){$.ajax(settings.ajaxOpts)})}})})(jQuery);


/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 4187 2007-12-16 17:15:27Z joern.zaefferer $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m )
					data = m[1];
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName )
					return undefined;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);


/*
 * nyroModal - jQuery Plugin
 * http://nyromodal.nyrodev.com
 *
 * Copyright (c) 2008 Cedric Nirousset (nyrodev.com)
 * Licensed under the MIT license
 *
 * $Date: 2009-08-14 (Fri, 14 Aug 2009) $
 * $version: 1.5.5
 */
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);
				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();
	};


	// -------------------------------------------------------
	// 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,

		css: { // 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 (from) {
			var jFrom = $(from).blur();
			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'}, 'css', 'content');
						modal.dataReady = true;
						if (modal.loadingShown || modal.transition)
							showContentOrLoading();
					})
					.attr('src', url);
				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);
					}
				}
				$.ajax($.extend(true, currentSettings.ajax, {
					url: url,
					success: ajaxLoaded,
					error: loadingError,
					data: data
				}));
				showModal();
			}
		} 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.marginLefttLoading+= currentSettings.marginScrollLeft;
			currentSettings.marginTopLoading+= currentSettings.marginScrollTop;
		}
	}

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

	// 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'}, 'css', '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
					}, 'css', '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({
					height: (body.height()+200)+'px', //130%
					width: (body.width()+200)+'px', //130%
					position: 'static',
					overflow: 'hidden'
				});
				$('html').css({overflow: 'hidden'});
				setCurrentSettings({
					css: {
						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.css.bg, {
										opacity: 0,
										zIndex: 50,
										border: 'none'
									}));
			}

			contain.append($('<div id="nyroModalFull"><div id="nyroModalBg"></div><div id="nyroModalWrapper"><div id="nyroModalContentMain"><div id="nyroModalContent"></div></div><div class="bottom-bar"></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.css.bg))
				.before(iframeHideIE);
			modal.bg.bind('click.nyroModal', clickBg);
			modal.loading = $('#nyroModalLoading')
				.css(currentSettings.css.loading)
				.hide();
			modal.contentWrapper = $('#nyroModalWrapper')
				.css(currentSettings.css.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;

		} 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.css.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();
		}

		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.css.content));
		modal.wrapper.css($.extend({}, tmp.wrapper2, currentSettings.css.wrapper2));

		if (!resizing)
			modal.contentWrapper.css($.extend({}, tmp.wrapper, currentSettings.css.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);
		modal.tmp.html(currentSettings.selector
			?filterScripts($('<div>'+data+'</div>').find(currentSettings.selector).contents())
			: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.css.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: ''});
			$('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.75, 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
function nyroModalDebug(msg, elts, settings) {
	if (elts.full)
		elts.bg.prepend(msg+'<br />');
}


/*!
 * slideViewerPro 1.0
 * Examples and documentation at: 
 * http://www.gcmingati.net/wordpress/wp-content/lab/jquery/svwt/
 * 2009 Gian Carlo Mingati
 * Version: 1.0.4 (12-AUGUST-2009)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Requires:
 * jQuery v1.3.2 or later
 * Option:
 * jQuery Timers plugin | plugins.jquery.com/project/timers (for autoslide mode)
 * 
 */
jQuery.extend( jQuery.easing, // from the jquery.easing plugin
{
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	}
});
jQuery(function(){
   jQuery("div.svwp").prepend("<img src='/themed/sgm/img/common/loader.gif' class='ldrgif' alt='loading...'/ >"); //change with YOUR loader image path   
});
var j = 0;
jQuery.fn.slideViewerPro = function(settings) {
	  settings = jQuery.extend({
			galBorderWidth: 0,
			thumbsTopMargin: 3, 
			thumbsRightMargin: 3,
			thumbsBorderWidth: 3,
			buttonsWidth: 20,
			thumbsLi: 165,
			galBorderColor: "#ff0000",
			thumbsBorderColor: "#d8d8d8",
			thumbsActiveBorderColor: "#ff0000",
			buttonsTextColor: "#ff0000",
			thumbsBorderOpacity: 1.0, // could be 0, 0.1 up to 1.0
			thumbsActiveBorderOpacity: 1.0, // could be 0, 0.1 up to 1.0
			easeTime: 750,
			asTimer: 4000,
			thumbs: 5,
			thumbsPercentReduction: 12,
			thumbsVis: true,
			easeFunc: "easeInOutExpo",
			leftButtonInner: "-", //could be an image "<img src='images/larw.gif' />" or an escaped char as "&larr";
			rightButtonInner: "+", //could be an image or an escaped char as "&rarr";
			autoslide: false,
			typo: false,
			typoFullOpacity: 0.9,
			shuffle: false
		}, settings);
		
	return this.each(function(){
		function shuffle(a) {
	    var i = a.size();
	    while (--i) {
	        var j = Math.floor(Math.random() * (i));
	        var tmp = a.slice(i, i+1);
	        a.slice(j, j+1).insertAfter(tmp);
	    }
		} 
		var container = jQuery(this);
		(!settings.shuffle) ? null : shuffle(container.find("li"));
		container.find("img.ldrgif").remove();
		container.removeClass("svwp").addClass("slideViewer");	
		container.attr("id", "svwp"+j);
		var pictWidth = container.find("img").attr("width");
		var pictHeight = container.find("img").attr("height");
		var pictEls = container.find("li").size();
		(pictEls >= settings.thumbs) ? null : settings.thumbs = pictEls;
		var slideViewerWidth = pictWidth*pictEls;
		var thumbsWidth = Math.round(pictWidth*settings.thumbsPercentReduction/100);
		var thumbsHeight =  Math.round(pictHeight*settings.thumbsPercentReduction/100);
		var pos = 0;
		var r_enabled = true;
		var l_enabled = true;
    container.find("ul").css("width" , slideViewerWidth)
    .wrap(jQuery("<div style='width:"+ pictWidth +"px;height:"+pictHeight+"px; overflow: hidden; position: relative; top: 0; left: 0'>"));
		container.css("width" , pictWidth);
		container.css("height" , pictHeight);
		container.each(function(i) {
			if(settings.typo)
			{
			jQuery(this).find("img").each(function(z) {
				//jQuery(this).after("<span class='typo' style='position: absolute; width:"+(pictWidth-12)+"px; margin: 0 0 0 -"+pictWidth+"px'>"+jQuery(this).attr("alt")+"<\/span>");
				jQuery(this).after("<span class='typo' style='position: absolute; width:"+(pictWidth-12-20)+"px; margin: 0 0 0 -"+pictWidth+"px'>"+jQuery(this).siblings('.img-info').html()+"<span href='#' class='more'>More information</span><\/span><\/span>");
				jQuery(this).siblings('.img-info').remove();
			});
			}
			jQuery(this).after("<div class='thumbSlider' id='thumbSlider" + j + "'><ul><\/ul><\/div>");
			jQuery(this).next().after("<a href='#' class='left' id='left" + j + "'>"+settings.leftButtonInner+"<\/a><a href='#' class='right' id='right" + j + "'><\/a>");
			
			jQuery(this).find("li").each(function(n) { 
				jQuery("div#thumbSlider" + j + " ul").append("<li style='width:"+settings.thumsbLi+"px'><div class='thumb-wrapper'><a title='" + jQuery(this).find("img").attr("alt") + "' href='#'><img width='"+ thumbsWidth +"' height='"+ thumbsHeight +"' src='" + jQuery(this).find("img").attr("src") + "' /></a></div><p class='tmbrdr'><a title='" + jQuery(this).find("img").attr("alt") + "' href='#'>"+jQuery(this).find("img").attr("alt")+"<\/a><\/p><\/li>");						
			});
    		// The thumbnails
			jQuery("div#thumbSlider" + j + " a").not('.tmbrdr a').each(function(z) {		
				jQuery(this).bind("click", function(){
					jQuery(this).find("p.tmbrdr").css({borderColor: settings.thumbsActiveBorderColor, opacity: settings.thumbsActiveBorderOpacity});
					jQuery(this).parent().parent().find("p.tmbrdr").not(jQuery(this).find("p.tmbrdr")).css({borderColor: settings.thumbsBorderColor, opacity: settings.thumbsBorderOpacity});
					var cnt = -(pictWidth*z);
					(cnt != container.find("ul").css("left").replace(/px/, "")) ? container.find("span.typo").animate({"opacity": 0}, 250) : null ;
					container.find("ul").animate({ left: cnt}, settings.easeTime, settings.easeFunc, function(){container.find("span.typo").animate({"opacity": settings.typoFullOpacity}, 250)});					
					return false;
				});
			});
			// The text links. Need to duplicate, otherwise meses up indices
			jQuery("div#thumbSlider" + j + " .tmbrdr a").each(function(z) {		
				jQuery(this).bind("click", function(){
					jQuery(this).find("p.tmbrdr").css({borderColor: settings.thumbsActiveBorderColor, opacity: settings.thumbsActiveBorderOpacity});
					jQuery(this).parent().parent().find("p.tmbrdr").not(jQuery(this).find("p.tmbrdr")).css({borderColor: settings.thumbsBorderColor, opacity: settings.thumbsBorderOpacity});
					var cnt = -(pictWidth*z);
					(cnt != container.find("ul").css("left").replace(/px/, "")) ? container.find("div.typo").animate({"opacity": 0}, 250) : null ;
					container.find("ul").animate({ left: cnt}, settings.easeTime, settings.easeFunc, function(){container.find("span.typo").animate({"opacity": settings.typoFullOpacity}, 250)});					
					return false;
				});
			});			
			// shortcuts to +/- buttons
			var jQuerybtl = jQuery("a#left" + j);	
			var jQuerybtr = jQuery("a#right" + j);	
			var totalThumbPadding = settings.thumbsPadding*2;
			// right/left 			
			jQuerybtr.bind("click", function(){
					if (r_enabled) (pictEls-pos > settings.thumbs*2 || pictEls%settings.thumbs == 0)? pos += settings.thumbs : pos += pictEls % settings.thumbs;
					r_enabled = false;
					jQuery(this).prev().prev().find("ul:not(:animated)").animate({ left: -(thumbsWidth+settings.thumbsRightMargin+totalThumbPadding)*pos}, 500, settings.easeFunc, function(){authorityMixing();});					
					return false;
			});
			jQuerybtl.bind("click", function(){	
					if (l_enabled && pos!=0) (pictEls-pos > settings.thumbs || pictEls%settings.thumbs == 0)? pos -= settings.thumbs : pos -= pictEls % settings.thumbs;
					l_enabled = false;
					jQuery(this).prev().find("ul:not(:animated)").animate({ left: -(thumbsWidth+settings.thumbsRightMargin+totalThumbPadding)*pos}, 500, settings.easeFunc, function(){authorityMixing();});
					return false;
			});
			
			function authorityMixing(){
				
				//right btt
				(pos == pictEls-settings.thumbs) ? jQuerybtr.addClass("r_dis") : jQuerybtr.removeClass("r_dis");
				(pos == pictEls-settings.thumbs) ? r_enabled = false : r_enabled = true;
				//left btt
				(pos == 0) ? jQuerybtl.addClass("l_dis") : jQuerybtl.removeClass("l_dis");
				(pos == 0) ? l_enabled = false : l_enabled = true;
			}
			
			//CSS	defs @ runtime
			var tBorder = settings.thumbsBorderWidth;
			var contBorder = settings.galBorderWidth
			jQuery(".slideViewer a img").css({
				border: "0",
				width: thumbsWidth-settings.thumbPadding*2+'px',
				height: thumbsHeight-settings.thumbPadding*2+'px'
			});
			jQuery("div.thumbSlider .thumb-wrapper").css({
				padding: settings.thumbsPadding+'px'
			});			
			if(settings.typo){
					jQuery(this).find("span.typo").each(function(z) {
						jQuery(this).css({
							opacity: settings.typoFullOpacity
						});
						var target_height = jQuery(this).innerHeight()-45;
						var original_top = jQuery(this).find('span.typo').css('top');
						var typos = jQuery(this);
						$(this).css('bottom', '-'+target_height+'px');

						jQuery(this).parent('li').bind("mouseenter mouseleave", function(e){
							if(typos.css('bottom') == '-'+target_height+'px'){
								typos.animate({ 'bottom': 0 }, 'slow');
							}else{
								typos.animate({ 'bottom': '-'+target_height+'px' }, 'slow');
							}
						});
					});
				}


			
			var corner_div = $('<div class="corners-outer">');
			corner_div.css({
				width: '20px',
				height: pictHeight,
				right: '0px',
				position: 'absolute'
			})
			jQuery("div#svwp"+ j).css({
				border: settings.galBorderWidth +"px solid "+settings.galBorderColor
			})
			.children('div')
			.before(corner_div)
			
				

			var thumbsPadding = settings.thumbsPadding*2;
			jQuery("div#thumbSlider" + j).css({
				position: "relative", 
				left: contBorder, 
				top: settings.thumbsTopMargin+"px", 
				//width: settings.thumbs*thumbsWidth+((settings.thumbsRightMargin*settings.thumbs)-(settings.thumbsRightMargin+totalThumbPadding)),
				width: settings.thumbSliderVisWidth+'px',
				textAlign: "center", 
				overflow: "hidden", 
				margin: "0 auto"
			})
			
			
			jQuery("div#thumbSlider" + j + " ul").css({
				width: (thumbsWidth*pictEls)+settings.thumbsRightMargin*pictEls + thumbsWidth , 
				position: "relative", 
				left: "0", 
				top: "0"
			});
			jQuery("div#thumbSlider" + j + " ul li").css({
				marginRight: settings.thumbsRightMargin,
				height: settings.thumbsHeight+'px',
				width: settings.thumbsLi+'px'
			});
					
			jQuery("div#thumbSlider" + j).find("p.tmbrdr").css({
				width: (thumbsWidth-tBorder*2 + settings.thumbsPadding)+"px", 
				//height: (thumbsHeight-tBorder*2) +"px", 
				height: "50px", 
				top: "0px"
				//border: settings.thumbsBorderWidth +"px solid "+settings.thumbsBorderColor, 
			});			
			jQuery("div#thumbSlider" + j + " a:first p.tmbrdr").css({
				borderColor: settings.thumbsActiveBorderColor, 
				opacity: settings.thumbsActiveBorderOpacity
			});
			authorityMixing();

			if(settings.autoslide){
					
					var i = 1;
					
					jQuery("div#thumbSlider" + j).everyTime(settings.asTimer, "asld", function() {			
		  			jQuery(this).find("a").eq(i).trigger("click");
		  			if(i == 0)
		  			{
						pos = 0;
						l_enabled = false;
						jQuery("div#thumbSlider" + j).find("ul:not(:animated)").animate({
							left: -(thumbsWidth+settings.thumbsRightMargin)*pos,
							opacity: 0
							}, 500, settings.easeFunc, function(){
								authorityMixing();
								$(this).animate({
									'opacity': 1
								}, 500)
								}
							);
		  			}
		  			else l_enabled = true;
		  			
						(i%settings.thumbs == 0)? jQuery(this).next().next().trigger("click") : null;
						(i < pictEls-1)?	i++ : i=0;		  			
					});		
					
					//stops autoslidemode	
					jQuery("a#right" + j).bind("mouseup", function(){
						jQuery(this).prev().prev().stopTime("asld");
		    	});
			}

			var uiDisplay = (settings.thumbsVis)? "block":"none";
			jQuery("div#thumbSlider" + j + ", a#left" + j + ", a#right" + j).wrapAll("<div style='width:"+ pictWidth +"px; position: relative;display: "+uiDisplay+"' id='ui"+j+"' class='slider-wrapper'><\/div>");			
			jQuery("div#svwp"+ j + ", div#ui" + j).wrapAll("<div style='width:"+ pictWidth +"px'><\/div>");
			});
			if(settings.thumbsVis){
				//$('#ui0').before("<h2>Other "+$('h1').text()+"</h2>");
				$('#ui0').before("<h2>"+$('input#thumb-title').attr('value')+"</h2>");
			}
			
		j++;
  });	
};


/*
 * jQuery validation plug-in 1.5.5
 *
 * 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 6403 2009-06-17 14:27:16Z 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;
			});
			
			// when a submitHandler is used, capture the submitting button
			if (validator.settings.submitHandler) {
				this.find("input, button").filter(":submit").click(function() {
					validator.submitButton = this;
				});
			}
		
			// 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 ) {
						if (validator.submitButton) {
							// insert a hidden input as a replacement for the missing submit button
							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
						}
						validator.settings.submitHandler.call( validator, validator.currentForm );
						if (validator.submitButton) {
							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
							hidden.remove();
						}
						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 = true;
            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;}
});

// constructor for validator
$.validator = function( options, form ) {
	this.settings = $.extend( {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

$.validator.format = function(source, params) {
	if ( arguments.length == 1 ) 
		return function() {
			var args = $.makeArray(arguments);
			args.unshift(source);
			return $.validator.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;
};

$.extend($.validator, {
	
	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		validClass: "valid",
		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.settings.validClass );
				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, validClass ) {
			$(element).addClass(errorClass).removeClass(validClass);
		},
		unhighlight: function( element, errorClass, validClass ) {
			$(element).removeClass(errorClass).addClass(validClass);
		}
	},

	// 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: $.validator.format("Please enter no more than {0} characters."),
		minlength: $.validator.format("Please enter at least {0} characters."),
		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
		range: $.validator.format("Please enter a value between {0} and {1}."),
		max: $.validator.format("Please enter a value less than or equal to {0}."),
		min: $.validator.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.parent( 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.settings.validClass );
				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.settings.validClass );
				}
			}
			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 || $.validator.messages[name];
		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) {
						var valid = response === true;
						if ( valid ) {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						} else {
							var errors = {};
							errors[element.name] = previous.message = response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						}
						previous.valid = valid;
						validator.stopRequest(element, valid);
					}
				}, 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.replace(/,/g, '|') : "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();
		}
		
	}
	
});

// deprecated, use $.validator.format instead
$.format = $.validator.format;

})(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);

function equalHeight(group) {
    tallest = 0;
    group.each(function() {
        thisHeight = $(this).height();
        if(thisHeight > tallest) {
            tallest = thisHeight;
        }
    });
    group.height(tallest);
}

/**
*
*	- Custom methods
---------------------------------------------------------------------------------------*/

/*	Builds a carousel with thumb nav	*/

function buildCarousel(){
   $("div.carousel").slideViewerPro({ 
	    thumbs: 4,   
	    typo: true, 
	    galBorderWidth: 0, 
	    thumbsBorderOpacity: 1, 
		thumbsRightMargin: 1,
		thumbsTopMargin: 0,
	    buttonsTextColor: "#707070", 
	    buttonsWidth: 100, 
	    thumbsActiveBorderOpacity:1, 
	    thumbsActiveBorderColor: "aqua", 
	    shuffle: false,
		thumbsPercentReduction: 20,
		thumbsHeight: 165,
		thumbsPadding: 10,// must be uniform padding on all four sides
		thumbsLi: 165,
		thumbSliderVisWidth: 665
	});
	return true;	
}
/*	Home slideshow	*/
$(function(){
   $('#home .img-holder').jParse({
       	ajaxOpts: {url: '/themed/sgm/xml/slides.home.xml'},
		parentElement: 'slide',
       	elementTag: ['source'],
       	output: '<img src="jpet0" />',
		limit: 5,
       	precallback: slides_start('#home .intro .img-holder', '#home .intro .img-holder img'),
       	callback: slides_finish('#home .intro .img-holder')
   });
});
/**
*	Makes use of the jquery.cycle plugin and creates animated slideshow with hover captions
*/

(function($){
	$.fn.extend({ 
		captionedSlideShow: function(options) {
		
			//Set the default values, use comma to separate the settings, example:
			var defaults = {
				width: '20px',
				height: '480px',
				right: '0px',
				top: '75px',
				bottom: '0px',
		        fx:     'fade',
		        speed:   500,
		        timeout: 5000,
				cornerDiv: true,
				fullCaption: false,
				buffer: 50,	// the original position of the info divs. Amount visible by default
				parentDiv: 'div.carousel-auto', //name of slides wrapper
				infoDiv: 'div.img-info'// name of info panel
			}

			var options =  $.extend(defaults, options);
			
			var animatedElement = $(this);
			
   		return this.each(function() {
   			var o = options;
				
				// apend a rounded corner to the bottom right. Proprietory to this site
				if(o.cornerDiv===true){

					var corner_div = $('<div class="corners-outer">');


					if(!$('div.carousel-wrapper .corners-outer').length){
						animatedElement.parents('div.carousel-wrapper').append(corner_div);					
					}
				}
				if(animatedElement.parents('div.carousel-wrapper').hasClass('full-caption')){
					var fullCaption = true;
				}else{
					var fullCaption = false;
				}
				
				var inner_list_items = $(this).find('.img-info ol li');
				
				$(inner_list_items).css({
					'height': '1em',
					'position': 'relative'
				});
				
				//console.log($(inner_list_items).html());
				animatedElement.each(function(){
					
					$(this).parents(o.parentDiv).addClass('animated');
					$('div.carousel-wrapper').addClass('animated');
					$(this).cycle({
				        fx:     o.fx,
				        speed:   o.speed,
				        timeout: o.timeout
				    });
					var typos = $(this).find('li').children(o.infoDiv);
					typos.css({
						'left': '0px'
					});
					
					if(!fullCaption){
						
						typos.each(function(){
							var target_height = $(this).innerHeight()-o.buffer;

							typos.css({
								'bottom': '-'+target_height+'px'
							});
							animatedElement.mouseenter(function(e){
							
								typos.animate({ 'bottom': 0 }, o.speed);
							});
							animatedElement.mouseleave(function(e){
								typos.animate({ 'bottom': '-'+target_height+'px'}, o.speed);
							});
						}).append("<span class='more'>More information<span>");
					}
					
				})
   			});
   		}
	});

})(jQuery);
/**
*	Corner rounding and adjustment
*
**/
function doCorners(){
	var rounded_elems_20 = $('.rounded, #primary .module.full-width, .pull-quote').not('.two-col #primary .module.full-width');
	var rounded_elems_10 = $('.module-inner').not('.three-col #primary .module.full-width .module-inner, .module-inner .module-content');

	settings_10 = {
       tl: { radius: 10 },
       tr: { radius: 1 },
       bl:  { radius: 1 },
       br: { radius: 10 },
       antiAlias: true,
       autoPad: true
   };
	if(!isIe6()){
		rounded_elems_10.corner(settings_10);
	}
	settings_20 = {
       tl: { radius: 20 },
       tr: { radius: 1 },
       bl:  { radius: 1 },
       br: { radius: 20 },
       antiAlias: true,
       autoPad: true
   };
	rounded_elems_20.corner(settings_20);
		
	// Need to make adjustments for inner module top margins

	var ccwrappers = $('.ccwrapper');

	// Apply the class and styles of the target element to the ccwrapper element
	ccwrappers.each(function(){
		var wrapper = $(this);
		
		
		
			wrapper
			.each(function(){
				wrapper
				.find('#ccoriginaldiv:first').not('.intro, .captioned-img-wrapper, .full-width, .pull-quote')
				.each(function(){
					if(!$(this).hasClass('module-inner')){
						var classes = $(this).attr('class');
						wrapper
						.css({
							'marginLeft': $(this).css('marginLeft'),
							'marginRight': $(this).css('marginRight'),
							'marginTop': $(this).css('marginTop'),
							'width': strip_px($(this).css('width'))+strip_px($(this).css('paddingLeft'))+strip_px($(this).css('paddingRight'))+'px',
							'padding' : 0
						}).removeClass('hasCorners');
					}
				})
			});
			wrapper.find('.pull-quote')
			.each(function(){
				$(this)
				.parents('.ccwrapper')
				.addClass('pull-quote-wrapper')
			});
			/*wrapper.find('.full-width')
			.each(function(){
				$(this)
				.parents('.ccwrapper')
				.addClass('full-width')
			})*/
		
		
	});
	$('.autoPadDiv').css({
		'padding': '0 15px'
	});
	// Content container must fill vertically to show the border
     $('#ccoriginaldiv .autoPadDiv .ccwrapper').css({   
		"marginTop" : "-10px",
		"marginBottom" : "-10px"
     });
	if(isIe6()){
		$('.three-col #primary .ccwrapper').css({
			'marginBottom': '10px',
			'paddingBottom': '0px'
		});
		$('.row,.ccwrapper').not('.three-col #primary .ccwrapper').css({
			'marginBottom': '0px',
			'paddingBottom': '0px'
		});
	}
}
/**
*	Methods for slide shows
*
**/
function slides_start(elem, elem_placeholder){
	$(elem_placeholder).remove();
	$(elem).fadeOut();
}
function slides_finish(elem){
	$(elem).fadeIn(500, function(){
		$(this).cycle({
			fx: 'fade' // choose your transition type, ex: fade, scrollUp, shuffle, etc...
		});
	});
}

/**
*	Toggle the top panel
*
**/
function toggleTopPanel(){
	var default_text = 'Whats in the background?';
	var top_panel = $('#top-panel-content');
	/*top_panel.addClass('hidden').hide();*/
	var toggle_link = '<a href="#" id="toggle-link">'+default_text+'</a>';
	$('#top-bar-links').append($('<span id="toggle">'+toggle_link+'</span>'));
	$('#top-bar-links #toggle-link').click(function(){
		top_panel
		.slideToggle("slow")
		$(this)
		.fadeOut(500, function(){
			$(this).html($(this).html() == default_text ? 'Close' : default_text)
		}).fadeIn();
		return false;
	})
}

/**
*	Custom content toggler
**/
(function($){
	$.fn.extend({ 
		toggleTips: function(options) {
			//Set the default values, use comma to separate the settings, example:
			var defaults = {
		        speed:   500,
		        startText: 'Show',
				closeText: 'Close',
				targetDiv: '.answer', //target to expand
				infoDiv: 'div.img-info'// name of info panel
			}

			var options =  $.extend(defaults, options);

   		return this.each(function() {
				var o = options;
				var toggle_link = '<p class="toggle"><span>'+o.startText+'</span></p>';
				$(this)
				.find(o.targetDiv)
				.hide()
				.after(toggle_link);
				$('p.toggle span').click(function(){
					$(this)
					.parents('li')
					.find(o.targetDiv)
					.slideToggle(o.speed)
					$(this)
					.fadeOut(o.speed, function(){
						$(this).text($(this).text()== o.startText ? o.closeText : o.startText);
					}).fadeIn(o.speed)
					
				})
   		});
   	}
	});

})(jQuery);





/*	
	Toggler for tips etc
*************************************************************************************/

(function($){
	$.fn.extend({ 
		toggleTips: function(options) {
			//Set the default values, use comma to separate the settings, example:
			var defaults = {
		        speed:   500,
		        startText: 'Show',
				closeText: 'Close',
				targetDiv: '.answer', //target to expand
				infoDiv: 'div.img-info'// name of info panel
			}

			var options =  $.extend(defaults, options);

   		return this.each(function() {
				var o = options;
				var toggle_link = '<p class="toggle"><span>'+o.startText+'</span></p>';
				$(this)
				.find(o.targetDiv)
				.hide()
				.after(toggle_link);
				$('p.toggle span').click(function(){
					$(this)
					.parents('li')
					.find(o.targetDiv)
					.slideToggle(o.speed)
					$(this)
					.fadeOut(o.speed, function(){
						$(this).text($(this).text()== o.startText ? o.closeText : o.startText);
					}).fadeIn(o.speed)
					
				})
   		});
   	}
	});

})(jQuery);

/*	
	Misc methods
*************************************************************************************/

/*
*	Centres the numbered links
*/

$.fn.extend({ 	
	//pass the options variable to the function
	centreNav: function(options) {
		return this.each(function() {
			var nav_width = ($(this).find('li').size() * 10) + $(this).find('li').size() * 5;
			$(this)
			.css('width', nav_width)
			.css('margin', '0 auto')
			.css('float', 'none');
			
			if(isIe6()){
				$(this).css('width', nav_width+10);
			}
		});
	}
});
//Removes 'px' from string
function strip_px(value) {
	if (typeof(value)!='string') return value;
	return parseInt((( value != "auto" && value.indexOf("%") == -1 && value != "" && value.indexOf("px") !== -1)? Math.round(value.slice(0, value.indexOf("px"))) : 0))
}
/*
*	Checks if browser is IE6
*/
function isIe6(){
	if( $.browser.msie && ($.browser.version < 7) ){
		return true;
	}else{
		return false;
	}
}

/*	Equal heights	*/
function equalHeight(group) {
   tallest = 0;
   group.each(function() {
       thisHeight = $(this).height();
       if(thisHeight > tallest) {
           tallest = thisHeight;
       }
   });
   group.height(tallest);
}






