jQuery.download = function(data){
	//url and data options required
	if( data ){ 
		jQuery('<form action="file.php?name='+data+'" method="post"></form>').appendTo('body').submit().remove();
	};
};

/*
 * One Click Upload - jQuery Plugin
 * Copyright (c) 2008 Michael Mitchell - http://www.michaelmitchell.co.nz
 */
(function($){
	$.fn.upload = function(options) {
		/** Merge the users options with our defaults */
		options = $.extend({
			name: 'file',
			enctype: 'multipart/form-data',
			action: 'engine_functions.php',
			autoSubmit: true,
			data: '', oid: 0, 
			onSubmit: function() { $('body').addClass('wait');  },
			onComplete: function(res) {
				res=JSON.parse(res); 
				$('.wait').removeClass('wait');
				if(res.response) {
				 	popup.show('newpht', 'name='+res.name+'&id='+res.id, 'Wytnij zdjęcie', 480,750)
				}else popup.show('info2','num=18', 'Błąd');
			},
			onSelect: function() {}
		}, options);

		return new $.ocupload(this, options);
	},
	
	$.ocupload = function(element, options) {
		/** Fix scope problems */
		var self = this;
	
		/** A unique id so we can find our elements later */
		var id = new Date().getTime().toString().substr(8);
		
		/** Upload Iframe */
		var iframe = $(
			'<iframe '+
				'id="iframe'+id+'" '+
				'name="iframe'+id+'"'+
			'></iframe>'
		).css({
			display: 'none',
			cursor: 'pointer'
		});
		
		/** Form */
		var form = $(
			'<form '+
				'method="post" '+
				'enctype="'+options.enctype+'" '+
				'action="'+options.action+'" '+
				'target="iframe'+id+'"'+
			'></form>'
		).css({
			position: 'absolute',
			top: 0,
			left: 0,
			cursor: 'pointer'
		});
		
		/** File Input */
		var input = $(
			'<input '+
				'name="'+options.name+'" '+
				'type="file" '+
			'/>'
		).css({
			position: 'relative',
			display: 'block',	
			opacity: 0,
			cursor: 'pointer'
		});
		/** Put everything together */
		element.wrap('<div id="ocup_'+options.data+'"></div>'); //container
			form.append(input);
			element.after(form);
			element.after(iframe);
	
		/** Find the container and make it nice and snug */
		var container = element.parent().css({
			overflow: 'hidden',
			cursor: 'pointer',
			position: 'relative'
		});
		
		/** Watch for file selection */
		input.change(function() {
			
			/** Do something when a file is selected. */
			self.onSelect(); 
			
			/** Submit the form automaticly after selecting the file */
			if(self.autoSubmit) {
				
				self.submit();
			}
		});
		
		/** Methods */
		$.extend(this, {
			autoSubmit: true,
			onSubmit: options.onSubmit,
			onComplete: options.onComplete,
			onSelect: options.onSelect,
			data: options.data,
			oid: options.oid,
			number: options.number,
			/** get filename */		
			filename: function() {
				return input.attr('value');
			},
			
			/** get/set name */
			name: function(name) {
				var name = name ? name : false;
				
				if(name) {
					input.attr('name', value);
				}
				else {
					return input.attr('name');
				}
			},
			
			/** get/set action */
			action: function(action) {
				var action = action ? action : false;
				
				if(action) {
					form.attr('action', action);
				}
				else {
					return form.attr('action');
				}
			},
			
			/** get/set enctype */
			enctype: function(enctype) {
				var enctype = enctype ? enctype : false;
				
				if(enctype) {
					form.attr('enctype', enctype);
				}
				else {
					return form.attr('enctype');
				}
			},
			
			/** set options */
			set: function(obj, value) {
				var value =	value ? value : false;
								
				function option(action, value) {
					switch(action) {
						default:
							throw new Error('[jQuery.ocupload.set] \''+action+'\' is an invalid option.');
							break;
						case 'name':
							self.name(value);
							break;
						case 'action':
							self.action(value);
							break;
						case 'enctype':
							self.enctype(value);
							break;
						case 'data':
							self.data(value);
							break;
						case 'oid':
							self.oid(value);
							break;
						case 'autoSubmit':
							self.autoSubmit = value;
							break;
						case 'onSubmit':
							self.onSubmit = value;
							break;
						case 'onComplete':
							self.onComplete = value;
							break;
						case 'onSelect':
							self.onSelect = value;
							break;
					}
				}				
				
				if(value) {
					option(obj, value);
				}
				else {				
					$.each(obj, function(key, value) {
						option(key, value);
					});
				}
			},
			
			/** Submit the form */
			submit: function() {
				/** Do something before we upload */
				this.onSubmit();
				var json='{\"command\":\"add_temp_photo\", \"data\":{\"name\":\"'+this.data+'\",\"id\":\"'+this.oid+'\"}}';
				
				/** add additional paramters before sending */
			
				form.append($(
						"<input id='json'"+
							"type='hidden' "+
							"name='json' "+
							"value='"+json+"' "+
						"/>"
				));
				
				
				/** Submit the actual form */
				form.submit(); 
				$('input#json').remove();
				/** Do something after we are finished uploading */
				iframe.unbind().load(function() {
					/** Get a response from the server in plain text */
					var myFrame = document.getElementById(iframe.attr('name'));
					var response = $(myFrame.contentWindow.document.body).text();
					
					/** Do something on complete */
					self.onComplete(response); //done :D
				});
			}
		});
	}
})(jQuery);

/*
 * Thickbox 3.1 - One Box To Rule Them All.
 * By Cody Lindley (http://www.codylindley.com)
 * Copyright (c) 2007 cody lindley
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/
		  
var tb_pathToImage = "layout/ajax-loader.gif";

/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/

//on page load call tb_init
$(document).ready(function(){   
	tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox
	imgLoader = new Image();// preload image
	imgLoader.src = tb_pathToImage;
});

//add thickbox to href & area elements that have a class of .thickbox
function tb_init(domChunk){
	$(domChunk).click(function(){
	var t = this.title || this.name || null;
	var a = this.href || this.alt;
	var g = this.rel || false;
	tb_show(t,a,g);
	this.blur();
	return false;
	});
}

function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link

	try {
		if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
			$("body","html").css({height: "100%", width: "100%"});
			$("html").css("overflow","hidden");
			if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
				$("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
				$("#TB_overlay").click(tb_remove);
			}
		}else{//all others
			if(document.getElementById("TB_overlay") === null){
				$("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");
				$("#TB_overlay").click(tb_remove);
			}
		}
		
		if(tb_detectMacXFF()){
			$("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash
		}else{
			$("#TB_overlay").addClass("TB_overlayBG");//use background and opacity
		}
		
		if(caption===null){caption="";}
		$("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
		$('#TB_load').show();//show loader
		
		var baseURL;
	   if(url.indexOf("?")!==-1){ //ff there is a query string involved
			baseURL = url.substr(0, url.indexOf("?"));
	   }else{ 
	   		baseURL = url;
	   }
	   
	   var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
	   var urlType = baseURL.toLowerCase().match(urlString);

		if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images
				
			TB_PrevCaption = "";
			TB_PrevURL = "";
			TB_PrevHTML = "";
			TB_NextCaption = "";
			TB_NextURL = "";
			TB_NextHTML = "";
			TB_imageCount = "";
			TB_FoundURL = false;
		

			if(imageGroup){
				TB_TempArray = $("a.thickbox").get();
			
				for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
					var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
						if (!(TB_TempArray[TB_Counter].href == url)) {						
							if (TB_FoundURL) {
								TB_NextCaption = TB_TempArray[TB_Counter].title;
								TB_NextURL = TB_TempArray[TB_Counter].href;
								TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Następne &gt;</a></span>";
							} else {
								TB_PrevCaption = TB_TempArray[TB_Counter].title;
								TB_PrevURL = TB_TempArray[TB_Counter].href;
								TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Poprzednie</a></span>";
							}
						} else {
							TB_FoundURL = true;
							TB_imageCount = ""; 										
						}
				}
			}
			
			imgPreloader = new Image();
			imgPreloader.onload = function(){		
			imgPreloader.onload = null;
				
			// Resizing large images - orginal by Christian Montoya edited by me.
			var pagesize = tb_getPageSize();
			var x = pagesize[0] - 150;
			var y = pagesize[1] - 150;
			var imageWidth = imgPreloader.width;
			var imageHeight = imgPreloader.height;
			if (imageWidth > x) {
				imageHeight = imageHeight * (x / imageWidth); 
				imageWidth = x; 
				if (imageHeight > y) { 
					imageWidth = imageWidth * (y / imageHeight); 
					imageHeight = y; 
				}
			} else if (imageHeight > y) { 
				imageWidth = imageWidth * (y / imageHeight); 
				imageHeight = y; 
				if (imageWidth > x) { 
					imageHeight = imageHeight * (x / imageWidth); 
					imageWidth = x;
				}
			}
			// End Resizing
			
			TB_WIDTH = imageWidth + 30;
			TB_HEIGHT = imageHeight + 60;
			$("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"...<div id='TB_secondLine'>" + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>Zamknij</a> lub Esc </div>"); 		
			
			$("#TB_closeWindowButton").click(tb_remove);
			
			if (!(TB_PrevHTML === "")) {
				function goPrev(){
					if($(document).unbind("click",goPrev)){$(document).unbind("click",goPrev);}
					$("#TB_window").remove();
					$("body").append("<div id='TB_window'></div>");
					tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
					return false;	
				}
				$("#TB_prev").click(goPrev);
			}
			
			if (!(TB_NextHTML === "")) {		
				function goNext(){
					$("#TB_window").remove();
					$("body").append("<div id='TB_window'></div>");
					tb_show(TB_NextCaption, TB_NextURL, imageGroup);				
					return false;	
				}
				$("#TB_next").click(goNext);
				
			}

			document.onkeydown = function(e){ 	
				if (e == null) { // ie
					keycode = event.keyCode;
				} else { // mozilla
					keycode = e.which;
				}
				if(keycode == 27){ // close
					tb_remove();
				} else if(keycode == 190){ // display previous image
					if(!(TB_NextHTML == "")){
						document.onkeydown = "";
						goNext();
					}
				} else if(keycode == 188){ // display next image
					if(!(TB_PrevHTML == "")){
						document.onkeydown = "";
						goPrev();
					}
				}	
			};
			
			tb_position();
			$("#TB_load").remove();
			$("#TB_ImageOff").click(tb_remove);
			$("#TB_window").css({display:"block"}); //for safari using css instead of show
			};
			
			imgPreloader.src = url;
		}else{//code to show html
			
			var queryString = url.replace(/^[^\?]+\??/,'');
			var params = tb_parseQuery( queryString );

			TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
			TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL
			ajaxContentW = TB_WIDTH - 30;
			ajaxContentH = TB_HEIGHT - 45;
			
			if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window		
					urlNoQuery = url.split('TB_');
					$("#TB_iframeContent").remove();
					if(params['modal'] != "true"){//iframe no modal
						$("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"...</div><div id='TB_closeAjaxWindow'> <a href='#' id='TB_closeWindowButton' title='Close'><img border='0'  src='layout/graphic/close_popup.png'/></a></div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 30)+"px;height:"+(ajaxContentH + 17)+"px;' > </iframe>");
					}else{//iframe modal
					$("#TB_overlay").unbind();
						$("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 30)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");
					}
			}else{// not an iframe, ajax
					if($("#TB_window").css("display") != "block"){
						if(params['modal'] != "true"){//ajax no modal
						$("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"...</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'><img border='0' src='layout/graphic/close_popup.png'/></a></div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");
						}else{//ajax modal
						$("#TB_overlay").unbind();
						$("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");	
						}
					}else{//this means the window is already up, we are just loading new content via ajax
						$("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";
						$("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";
						$("#TB_ajaxContent")[0].scrollTop = 0;
						$("#TB_ajaxWindowTitle").html(caption);
					}
			}
					
			$("#TB_closeWindowButton").click(tb_remove);
			
				if(url.indexOf('TB_inline') != -1){	
					$("#TB_ajaxContent").append($('#' + params['inlineId']).children());
					$("#TB_window").unload(function () {
						$('#' + params['inlineId']).append( $("#TB_ajaxContent").children() ); // move elements back when you're finished
					});
					tb_position();
					$("#TB_load").remove();
					$("#TB_window").css({display:"block"}); 
				}else if(url.indexOf('TB_iframe') != -1){
					tb_position();
					if($.browser.safari){//safari needs help because it will not fire iframe onload
						$("#TB_load").remove();
						$("#TB_window").css({display:"block"});
					}
				}else{
					$("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method
						tb_position();
						$("#TB_load").remove();
						tb_init("#TB_ajaxContent a.thickbox");
						$("#TB_window").css({display:"block"});
					});
				}
			
		}

		if(!params['modal']){
			document.onkeyup = function(e){ 	
				if (e == null) { // ie
					keycode = event.keyCode;
				} else { // mozilla
					keycode = e.which;
				}
				if(keycode == 27){ // close
					tb_remove();
				}	
			};
		}
		
	} catch(e) {
		//nothing here
	}
}

//helper functions below
function tb_showIframe(){
	$("#TB_load").remove();
	$("#TB_window").css({display:"block"});
}

function tb_remove() {
 	$("#TB_imageOff").unbind("click");
	$("#TB_closeWindowButton").unbind("click");
	$("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
	$("#TB_load").remove();
	if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
		$("body","html").css({height: "auto", width: "auto"});
		$("html").css("overflow","");
	}
	document.onkeydown = "";
	document.onkeyup = "";
	return false;
}

function tb_position() {
$("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});
	if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
		$("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
	}
}

function tb_parseQuery ( query ) {
   var Params = {};
   if ( ! query ) {return Params;}// return empty object
   var Pairs = query.split(/[;&]/);
   for ( var i = 0; i < Pairs.length; i++ ) {
      var KeyVal = Pairs[i].split('=');
      if ( ! KeyVal || KeyVal.length != 2 ) {continue;}
      var key = unescape( KeyVal[0] );
      var val = unescape( KeyVal[1] );
      val = val.replace(/\+/g, ' ');
      Params[key] = val;
   }
   return Params;
}

function tb_getPageSize(){
	var de = document.documentElement;
	var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
	var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
	arrayPageSize = [w,h];
	return arrayPageSize;
}

function tb_detectMacXFF() {
  var userAgent = navigator.userAgent.toLowerCase();
  if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
    return true;
  }
}


/**
 * jQuery custom checkboxes
 * 
 * Copyright (c) 2008 Khavilo Dmitry (http://widowmaker.kiev.ua/checkbox/)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * @version 1.1.0 Beta
 * @author Khavilo Dmitry
 * @mailto wm.morgun@gmail.com
**/
(function($){

	$.fn.checkbox = function(options) {
	
		/* IE6 background flicker fix */
		try	{ document.execCommand('BackgroundImageCache', false, true);	} catch (e) {}
		
		/* Default settings */
		var settings = {
			cls: 'jquery-checkbox',  /* checkbox  */
			empty: 'empty.png'  /* checkbox  */
		};
		
		/* Processing settings */
		settings = $.extend(settings, options || {});
		
		/* Adds check/uncheck & disable/enable events */
		var addEvents = function(object)
		{
			var checked = object.checked;
			var disabled = object.disabled;
			var $object = $(object);
			
			if ( object.stateInterval )
				clearInterval(object.stateInterval);
			
			object.stateInterval = setInterval(
				function() 
				{
					if ( object.disabled != disabled )
						$object.trigger( (disabled = !!object.disabled) ? 'disable' : 'enable');
					if ( object.checked != checked )
						$object.trigger( (checked = !!object.checked) ? 'check' : 'uncheck');
				}, 
				10 /* in miliseconds. Low numbers this can decrease performance on slow computers, high will increase responce time */
			);
			return $object;
		}
		try { console.log(this); } catch(e) {}
		/* Wrapping all passed elements */
		return this.each(function() 
		{
			var ch = this;
			var $ch = addEvents(ch); /* Adds custom eents and returns */
			
			if (ch.wrapper)
			{
				ch.wrapper.remove();
			}
			
			/* Creating div for checkbox and assigning "hover" event */
			ch.wrapper = $('<div class="' + settings.cls + '-box"><div class="' + settings.cls + '"><div class="mark"><img src="' + settings.empty + '" /></div></div></div>');
			ch.wrapperInner = ch.wrapper.children('span');
			ch.wrapper.hover(
				function() { ch.wrapperInner.addClass(settings.cls + '-hover'); },
				function() { ch.wrapperInner.removeClass(settings.cls + '-hover'); }
			);

			/* Wrapping checkbox */
			$ch.css({position: 'absolute', zIndex: -1}).after(ch.wrapper);
			
			/* Fixing IE6 label behaviour */
			var parents = $ch.parents('label');
			/* Creating "click" event handler for checkbox wrapper*/
			if ( parents.length )
			{
				parents.click(function(e) { $ch.trigger('click', [e]); return ( $.browser.msie && $.browser.version < 7 ); });
			}
			else
			{
				ch.wrapper.click(function(e) { $ch.trigger('click', [e]); });
			}
			
			delete parents;
				
			$ch.bind('disable', function() { ch.wrapperInner.addClass(settings.cls+'-disabled');}).bind('enable', function() { ch.wrapperInner.removeClass(settings.cls+'-disabled');});
			$ch.bind('check', function() { ch.wrapper.addClass(settings.cls+'-checked' );}).bind('uncheck', function() { ch.wrapper.removeClass(settings.cls+'-checked' );});
			
			/* Disable image drag-n-drop  */
			$('img', ch.wrapper).bind('dragstart', function () {return false;}).bind('mousedown', function () {return false;});
			
			/* Firefox div antiselection hack */
			if ( window.getSelection )
				ch.wrapper.css('MozUserSelect', 'none');
			
			/* Applying checkbox state */
			if ( ch.checked )
				ch.wrapper.addClass(settings.cls + '-checked');
			if ( ch.disabled )
				ch.wrapperInner.addClass(settings.cls + '-disabled');
		});
	};


})(jQuery);
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-22 01:45:56 +0200 (Son, 22 Jul 2007) $
 * $Rev: 2447 $
 *
 * Version 2.1.1
 */
(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery);

/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-21 18:45:56 -0500 (Sat, 21 Jul 2007) $
 * $Rev: 2447 $
 *
 * Version 2.1.1
 */
(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery);


(function($) {

    /**
     * autor: CTAPbIu_MABP
     * email: ctapbiumabp@gmail.com
     * site: http://mabp.kiev.ua/content/2008/04/08/autocomplete/
     * license: MIT & GPL
     * last update: 19.02.2009
     * version: 1.3
     */

    var ac = function(c, o) {
        this.cache = {}; // main chache {mask:[text]}
        this.store = {}; // secondary cache {mask:strind}
        this.pairs = {}; // cache of values {text:value}
        this.init(c, o);
    };

    ac.prototype = {

        // html elements
        ac : null, // main input
        ul : null, // autocomplete list
        img : null, // image
        container : null, // outer div

        // timeouts
        close : null, // ac hide
        timeout : null, // ac search

        // system definitons
        chars : 0, // previous search string lenght

        // user definitons
        url : 'engine_functions.php', // url for ajax request
        source : null, // <select/>, [], {} jQuery
        minchar : null, // minchars
        delay : 50, // for search
        fillin : false, // pre fill-in
        type : 'xml', // ajax data type
        width : 200, // width
        top : false, // position top/bottom
        writable : true, // writeable/selectable
        values : false, // store values

        // events, please use 'self' instead of 'this'
        onSelect : function () {
        },
        onSetup : function () {
        },
        onKeyPress : function () {
        },
        onSuggest : function () {
        },
        onError : function () {
        },
        onSuccess : function () {
        },
        onDisplay : function () {
        },

        init : function (ac, options) {
            var self = $.extend(this, options);

            self.container = $('<div/>')
                .css({width:self.width})
                .addClass('ac_conteiner')
                .insertBefore(ac);
            self.ac = $(ac)
                .attr({autocomplete:'off'})
                .bind('blur', function() {
                    clearTimeout(self.close);
                    self.close = setTimeout(function() {
                        self.ul.hide();
                    }, 300);
                })  // IE bug self.ul[.hide()] = undefined
                .css({width:self.width-22}) // 18 img + 2 margin + 2 border
                .addClass('ac_input')
                .appendTo(self.container);
            self.img = $('<div/>')
                .bind("click", function() {
                    clearTimeout(self.close);
                    self.scroll();
                    self.ul.toggle();
                    self.ac.focus();
                })
                .addClass('ac_img')
                .appendTo(self.container);
            self.ul = $('<div/>')
                .addClass('ac_results')
                .appendTo(self.container)
                .bind("click", function() {
                    self.select();
                    self.ac.focus();
                });

            $(window).bind('resize load', function() {
                var c = self.container;
                self.ul.css({
                    width:self.width,
                    top:(   self.top ?
                            c.offset().top - self.ul.height() - parseInt(c.css('border-top-width')) :
                            c.offset().top + c.height() + parseInt(c.css('border-top-width')) ),
                    left:(c.offset().left + parseInt(c.css('border-left-width')))
                });
            });

            if ($.browser.mozilla)
                self.ac.bind('keypress', self, self.process);
            else
                self.ac.bind('keydown', self, self.process);

            self.onSetup.apply(self,arguments);

            if (self.fillin)
                self.suggest('hide');
        },

        process : function (e) {
            var self = e.data, len = self.ac.val().length;
            self.onKeyPress.apply(self,arguments);

            if ((/27$|38$|40$/.test(e.keyCode) && self.ul.is(':visible')) || (/^13$|^9$/.test(e.keyCode) && self.get())) {
                e.preventDefault();
                e.stopPropagation();
                switch (e.keyCode) {
                    case 38: // up
                        self.prev();
                        break;
                    case 40: // down
                        self.next();
                        break;
                    case 9:  // tab
                    case 13: // return
                        self.select();
                        break;
                    case 27: // escape
                        self.ul.hide();
                        break;
                }
            } else if (len != self.chars || !len) {
                self.chars = len;
                if (self.timeout)
                    clearTimeout(self.timeout);
                self.timeout = setTimeout(function() {
                    self.suggest('show');
                }, self.delay);
            }
        },

        get : function() {
            var self = this;
            return self.ul.find('.ac_over');
        },

        prev : function () {
            var self = this, current = self.get(), prev = current.prev();
            if (current.length) {
                current.removeClass('ac_over');
                if (prev.text())
                    prev.addClass('ac_over');
                }
            if (!current.length || !prev.text()){
                self.ul.children(':last').addClass('ac_over');
            }
            self.scroll();
        },

        next : function () {
            var self = this, current = self.get(), next = current.next();
            if (current.length) {
                current.removeClass('ac_over');
                if (next.text())
                    next.addClass('ac_over');
            }
            if (!current.length || !next.text())
                self.ul.children(':first').addClass('ac_over');
            self.scroll();
        },

        scroll : function(){
            var self = this, current = self.get();
            if (!current.length)
                return; // quick return
            var el = current.get(0), list = self.ul.get(0); // dont scroll after click on document :(
            if(el.offsetTop + el.offsetHeight > list.scrollTop + list.clientHeight)
                list.scrollTop = el.offsetTop + el.offsetHeight - list.clientHeight;
            else if(el.offsetTop < list.scrollTop)
                list.scrollTop = el.offsetTop;
        },

        select : function () {
            var self = this, current = self.get();
            if (current) {
                self.ac.val(current.text());
                self.ul.hide();
                self.onSelect.apply(self,arguments);
            }
        },

        suggest : function (show) {
            var self = this, mask = $.trim(self.ac.val());
            self.ul.hide();
            if (mask.length >= self.minchar) {
                self.onSuggest.apply(self,arguments);
                if (self.check(mask))
                    self.prepare(self.grab(mask),mask)[show]();
                else if (self.url) // use ajax
                    $.ajax({type: "GET", url:self.url, data:{mask:mask},
                        success:function(xml) {
                            self.onSuccess.apply(self,arguments);
                            self.prepare(xml,mask)[show]();
                        },
                        error:function(){
                            self.onError.apply(self,arguments);
                        },
                        dataType:self.type
                    });
                else if (self.source) // use source
                    self.prepare(self.source,mask)[show]();
            }else{
                self.ul.empty();
            }
        },

        check: function (mask){
            var self = this;
            if (self.cache[mask])
                return true; // quick return
            mask = mask.toLowerCase();
            for(var it in self.cache)
                if (it && !mask.indexOf(it.toLowerCase()))
                    return true;
            return false;
        },

        grab: function (mask){
            var self = this, map = [], array = [];
            if (self.cache[mask])
                return self.cache[mask]; // quick return
            for(var it in self.cache)
                array.push(it);
            array = array.reverse();
            mask = mask.toLowerCase();
            for(var item in array)
                if(!mask.indexOf(array[item].toLowerCase())){
                    for(var word in self.cache[array[item]])
                        if (!self.cache[array[item]][word].toLowerCase().indexOf(mask))
                            map.push(self.cache[array[item]][word]);
                    break;
                }
            return map;
        },

        prepare : function(xml, mask){
            var self = this, list = [], map = [], options = $('option', xml);
            if (!self.store[mask]){
                if(options.length)
                    options.each(function(i, n) {  // use selectbox or ajax result
                        var t = $(n).text();
                        map.push(t);
                        list.push(self.mark(t,mask));
                        if(self.values && !self.pairs[t]){
                            self.pairs[t] = $(n).attr("value");
                        }
                    });
                else
                    $.each(xml, function(i, n) { // use array or array-like object
                        map.push(n);
                        list.push(self.mark(n,mask));
                        if(self.values && !self.pairs[n])
                            self.pairs[n] = i;
                    });
                self.cache[mask] = map;
                self.store[mask] = list.join('');
            }

            if (!self.writable && !self.cache[mask].length){
                setTimeout(function(){
                    var val = self.ac.val();
                    self.ac.val(val.substring(0, val.length-1));
                    self.chars--;
                },50);
                return self.ul;
            }
            return self.display(self.store[mask]);
        },

        mark : function(text, mask){
            if (new RegExp('^' + mask, 'ig').test(text))
                return '<div>' + text.replace(new RegExp('^' + mask, 'ig'), function(mask) {
                    return '<span class="ac_match">' + mask + '</span>';
                }) + '</div>';
        },

        display : function (list) {
            var self = this;
            self.onDisplay.apply(self,arguments);
            if (!list)
                return self.ul;
            return self.ul.empty().append(list).find('div').mouseover(function() {
                    $(this).siblings().removeClass('ac_over').end().addClass('ac_over');
                }).filter(":first").addClass('ac_over').end().end(); // ul
        }
    };

    $.fn.autocomplete = function(options) {
        this.each(function() {
            new ac(this, options);
        });
        return this;
    };

})(jQuery);

/**
  * Version 1.6.1
  *
  * ** means there is basic unit tests for this parameter. 
  *
  * @name  Jeditable
  * @type  jQuery
  * @param String  target             (POST) URL or function to send edited content to **
  * @param Hash    options            additional options 
  * @param String  options[method]    method to use to send edited content (POST or PUT) **
  * @param Function options[callback] Function to run after submitting edited content **
  * @param String  options[name]      POST parameter name of edited content
  * @param String  options[id]        POST parameter name of edited div id
  * @param Hash    options[submitdata] Extra parameters to send when submitting edited content.
  * @param String  options[type]      text, textarea or select (or any 3rd party input type) **
  * @param Integer options[rows]      number of rows if using textarea ** 
  * @param Integer options[cols]      number of columns if using textarea **
  * @param Mixed   options[height]    'auto', 'none' or height in pixels **
  * @param Mixed   options[width]     'auto', 'none' or width in pixels **
  * @param String  options[loadurl]   URL to fetch input content before editing **
  * @param String  options[loadtype]  Request type for load url. Should be GET or POST.
  * @param String  options[loadtext]  Text to display while loading external content.
  * @param Hash    options[loaddata]  Extra parameters to pass when fetching content before editing.
  * @param String  options[data]      Or content given as paramameter. **
  * @param String  options[indicator] indicator html to show when saving
  * @param String  options[tooltip]   optional tooltip text via title attribute **
  * @param String  options[event]     jQuery event such as 'click' of 'dblclick' **
  * @param String  options[onblur]    'cancel', 'submit', 'ignore' or function ??
  * @param String  options[submit]    submit button value, empty means no button **
  * @param String  options[cancel]    cancel button value, empty means no button **
  * @param String  options[cssclass]  CSS class to apply to input form. 'inherit' to copy from parent. **
  * @param String  options[style]     Style to apply to input form 'inherit' to copy from parent. **
  * @param String  options[select]    true or false, when true text is highlighted ??
  * @param String  options[placeholder] Placeholder text or html to insert when element is empty. **
  *             
  */

(function($) {

    $.fn.editable = function(target, options) {
        var settings = {
            target     : target,
            name       : 'value',
            id         : 'id',
            type       : 'text',
            width      : 'auto',
            height     : 'auto',
            event      : 'click',
            onblur     : 'submit',
            loadtype   : 'GET',
            loadtext   : 'Loading...',
            placeholder: 'Kliknij żeby edytować',
            loaddata   : {},
            submitdata : {}
        };
        
        if(options) {
            $.extend(settings, options);
        }
    
        /* setup some functions */
        var plugin   = $.editable.types[settings.type].plugin || function() { };
        var submit   = $.editable.types[settings.type].submit || function() { };
        var buttons  = $.editable.types[settings.type].buttons 
                    || $.editable.types['defaults'].buttons;
        var content  = $.editable.types[settings.type].content 
                    || $.editable.types['defaults'].content;
        var element  = $.editable.types[settings.type].element 
                    || $.editable.types['defaults'].element;
        var reset    = $.editable.types[settings.type].reset 
                    || $.editable.types['defaults'].reset;
        var callback = settings.callback || function() { };
        
        /* add custom event if it does not exist */
        if  (!$.isFunction($(this)[settings.event])) {
            $.fn[settings.event] = function(fn){
          		return fn ? this.bind(settings.event, fn) : this.trigger(settings.event);
          	}
        }
          
        /* TODO: remove this when form is displayed */
        $(this).attr('title', settings.tooltip);
        
        settings.autowidth  = 'auto' == settings.width;
        settings.autoheight = 'auto' == settings.height;

        return this.each(function() {

            /* save this to self because this changes when scope changes */
            var self = this;  
                   
            /* inlined block elements lose their width and height after first edit */
            /* save them for later use as workaround */
            var savedwidth  = $(self).width();
            var savedheight = $(self).height();
            
            /* if element is empty add something clickable (if requested) */
            if (!$.trim($(this).html())) {
                $(this).html(settings.placeholder);
            }
            
            $(this)[settings.event](function(e) {
	
                /* prevent throwing an exeption if edit field is clicked again */
                if (self.editing) {
                    return;
                }

                /* figure out how wide and tall we are, saved width and height */
                /* are workaround for http://dev.jquery.com/ticket/2190 */
                if (0 == $(self).width()) {
                    //$(self).css('visibility', 'hidden');
                    settings.width  = savedwidth;
                    settings.height = savedheight;
                } else {
                    if (settings.width != 'none') {
                        settings.width = 
                            settings.autowidth ? $(self).width()  : settings.width;
                    }
                    if (settings.height != 'none') {
                        settings.height = 
                            settings.autoheight ? $(self).height() : settings.height;
                    }
                }
                //$(this).css('visibility', '');
                
                /* remove placeholder text, replace is here because of IE */

                if ($(this).html().toLowerCase().replace(/;/, '') == 
                    settings.placeholder.toLowerCase().replace(/;/, '')) 
			{  $(this).html(''); }
                                
                self.editing  = true;
                self.revert   = $(self).html().replace(/<br>/gi, "\n").replace(/^\s+/,"");
		//self.revert   = $(self).html().replace(/<BR>/g, "\n").replace(/^\s+/,"");
                $(self).html('');

                /* create the form object */
                var form = $('<form/>');
                
                /* apply css or style or both */
                if (settings.cssclass) {
                    if ('inherit' == settings.cssclass) {
                        form.attr('class', $(self).attr('class'));
                    } else {
                        form.attr('class', settings.cssclass);
                    }
                }

                if (settings.style) {
                    if ('inherit' == settings.style) {
                        form.attr('style', $(self).attr('style'));
                        /* IE needs the second line or display wont be inherited */
                        form.css('display', $(self).css('display'));                
                    } else {
                        form.attr('style', settings.style);
                    }
                }

                /* add main input element to form and store it in input */
                var input = element.apply(form, [settings, self]);

                /* set input content via POST, GET, given data or existing value */
                var input_content;
                
                if (settings.loadurl) {
                    var t = setTimeout(function() {
                        input.disabled = true;
                        content.apply(form, [settings.loadtext, settings, self]);
                    }, 100);

                    var loaddata = {};
                    loaddata[settings.id] = self.id;
                    if ($.isFunction(settings.loaddata)) {
                        $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
                    } else {
                        $.extend(loaddata, settings.loaddata);
                    }
                    $.ajax({
                       type : settings.loadtype,
                       url  : settings.loadurl,
                       data : loaddata,
                       async : false,
                       success: function(result) {
                       	  window.clearTimeout(t);
                       	  input_content = result;
                          input.disabled = false;
                       }
                    });
                } else if (settings.data) {
                    input_content = settings.data;
                    if ($.isFunction(settings.data)) {
                        input_content = settings.data.apply(self, [self.revert, settings]);
                    }
                } else {
                    input_content = self.revert; 
                }
                content.apply(form, [input_content, settings, self]);

                input.attr('name', settings.name);
        
                /* add buttons to the form */
                buttons.apply(form, [settings, self]);
         
                /* add created form to self */
                $(self).append(form);
         
                /* attach 3rd party plugin if requested */
                plugin.apply(form, [settings, self]);

                /* focus to first visible form element */
                $(':input:visible:enabled:first', form).focus();

                /* highlight input contents when requested */
                if (settings.select) {
                    input.select();
                }
        
                /* discard changes if pressing esc */
                input.keydown(function(e) {
                    if (e.keyCode == 27) {
                        e.preventDefault();
                        //self.reset();
                        reset.apply(form, [settings, self]);
                    }
                });

                /* discard, submit or nothing with changes when clicking outside */
                /* do nothing is usable when navigating with tab */
                var t;
                if ('cancel' == settings.onblur) {
                    input.blur(function(e) {
                        //t = setTimeout(self.reset, 500);
                        t = setTimeout(function() {
                            reset.apply(form, [settings, self]);
                        }, 500);
                    });
                } else if ('submit' == settings.onblur) {
                    input.blur(function(e) {
                        form.submit();
                    });
                } else if ($.isFunction(settings.onblur)) {
                    input.blur(function(e) {
                        settings.onblur.apply(self, [input.val(), settings]);
                    });
                } else {
                    input.blur(function(e) {
                      /* TODO: maybe something here */
                    });
                }

                form.submit(function(e) {

                    if (t) { 
                        clearTimeout(t);
                    }

                    /* do no submit */
                    e.preventDefault(); 
            
                    /* call before submit hook. if it returns false abort submitting */
                    if (false !== submit.apply(form, [settings, self])) { 
                      
                      /* check if given target is function */
                      if ($.isFunction(settings.target)) {
                          var str = settings.target.apply(self, [input.val(), settings]);
                          $(self).html(str);
                          self.editing = false;
                          callback.apply(self, [self.innerHTML, settings]);
                          /* TODO: this is not dry */                              
                          if (!$.trim($(self).html())) {
                              $(self).html(settings.placeholder);
                          }
                      } else {
                          /* add edited content and id of edited element to POST */
                          var submitdata = {};
                          submitdata[settings.name] = input.val();
                          submitdata[settings.id] = self.id;
                          /* add extra data to be POST:ed */
                          if ($.isFunction(settings.submitdata)) {
                              $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
                          } else {
                              $.extend(submitdata, settings.submitdata);
                          }
                          
                          /* quick and dirty PUT support */
                          if ('PUT' == settings.method) {
                              submitdata['_method'] = 'put';
                          }
                          /* show the saving indicator */
                         // $(self).html(settings.indicator);
			 var json={"command":"edit_"+settings.obj, "data":{"id":self.id, "value":input.val(), "attr":settings.oid }};

			  $.ajax({
					url: "engine_functions.php",type: "post",dataType: "json",
					data: 'json='+JSON.stringify(json),
					success: function(res) {
						$(self).html(res.response); 
                             			self.editing = false;
                              			callback.apply(self, [self.innerHTML, settings]);
                              			/* TODO: this is not dry */                              
                              			if (!$.trim($(self).html())) {
                                 		$(self).html(settings.placeholder);
                             			 }	
					}	
			   });
                      }
                      
                    }
                     
                    return false;
                });
            });
            
            /* privileged methods */
            this.reset = function() {
                $(self).html(self.revert.replace(/\n/g, "<br>"));
                self.editing   = false;
                if (!$.trim($(self).html())) {
			
                    $(self).html(settings.placeholder);
                }
            }            
        });

    };


    $.editable = {
        types: {
            defaults: {
                element : function(settings, original) {
                    var input = $('<input type="hidden">');                
                    $(this).append(input);
                    return(input);
                },
                content : function(string, settings, original) {
                    $(':input:first', this).val(string);
                },
                reset : function(settings, original) {
                  original.reset();
                },
                buttons : function(settings, original) {
                    var form = this;
                    if (settings.submit) {
                        /* if given html string use that */
                        if (settings.submit.match(/>$/)) {
                            var submit = $(settings.submit).click(function() {
                                if (submit.attr("type") != "submit") {
                                    form.submit();
                                }
                            });
                        /* otherwise use button with given string as text */
                        } else {
                            var submit = $('<button type="submit">');
                            submit.html('');                            
                        }
                        $(this).append(submit);
                    }
                    if (settings.cancel) {
                        /* if given html string use that */
                        if (settings.cancel.match(/>$/)) {
                            var cancel = $(settings.cancel);
                        /* otherwise use button with given string as text */
                        } else {
                            var cancel = $('<button type="cancel">');
                            cancel.html(settings.cancel);
                        }
                        $(this).append(cancel);

                        $(cancel).click(function(event) {
                            //original.reset();
                            if ($.isFunction($.editable.types[settings.type].reset)) {
                                var reset = $.editable.types[settings.type].reset;                                                                
                            } else {
                                var reset = $.editable.types['defaults'].reset;                                
                            }
                            reset.apply(form, [settings, original]);
                            return false;
                        });
                    }
                }
            },
            text: {
                element : function(settings, original) {
                    var input = $('<input>');
                    if (settings.width  != 'none') { input.width(settings.width);  }
                    if (settings.height != 'none') { input.height(settings.height); }
                    /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
                    //input[0].setAttribute('autocomplete','off');
                    input.attr('autocomplete','off');
                    $(this).append(input);
                    return(input);
                }
            },
            textarea: {
                element : function(settings, original) {
                    var textarea = $('<textarea>');
                    if (settings.rows) {
                        textarea.attr('rows', settings.rows);
                    } else {
                        textarea.height(settings.height);
						textarea.autogrow();
                    }
                    if (settings.cols) {
                        textarea.attr('cols', settings.cols);
                    } else {
                        textarea.width(settings.width);
                    }
		    textarea.keypress( function (e) {  
			if(e.keyCode == 8 || e.keyCode==46) return true;	
			else return ($(this).val().length  <= settings.len); 
		    })
                    $(this).append(textarea);
                    return(textarea);
                }
            },
            select: {
               element : function(settings, original) {
                    var select = $('<select>');
                    $(this).append(select);
                    return(select);
                },
                content : function(string, settings, original) {
                    if (String == string.constructor) { 	 
                        eval ('var json = ' + string);
                        for (var key in json) {
                            if (!json.hasOwnProperty(key)) {
                                continue;
                            }
                            if ('selected' == key) {
                                continue;
                            } 
                            var option = $('<option>').val(key).append(json[key]);
                            $('select', this).append(option); 	 
                        }
                    }
                    /* Loop option again to set selected. IE needed this... */ 
                    $('select', this).children().each(function() {
                        if ($(this).val() == json['selected'] || 
                            $(this).text() == original.revert) {
                                $(this).attr('selected', 'selected');
                        };
                    });
                }
            }
        },

        /* Add new input type */
        addInputType: function(name, input) {
            $.editable.types[name] = input;
        }
    };

})(jQuery);


$.editable.addInputType('growfield', {
    element : function(settings, original) {
        var textarea = $('<textarea>');
        if (settings.rows) {
            textarea.attr('rows', settings.rows);
        } else {
            textarea.height(settings.height);
        }
        if (settings.cols) {
            textarea.attr('cols', settings.cols);
        } else {
            textarea.width(settings.width);
        }
        // will execute when textarea is rendered
        textarea.ready(function() {
                // implement your scroll pane code here
        });
        $(this).append(textarea);
        return(textarea);
    },
    plugin : function(settings, original) {
        // applies the growfield effect to the in-place edit field
        $('textarea', this).growfield(settings.growfield);
    }
});

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(c($){$.G.2e=c(u){6.I(c(){6.y=b;L a=$(6);8(6.2f.K()!=\'2b\')e f;8(!u)u={};L C=6;6.7={k:(A(u.k)!=\'P\'?u.k:b),N:(A(u.N)!=\'P\'?u.N:b),F:(A(u.1P)!=\'P\'?u.1P:0),1i:(u.1i||1h),13:(u.13||1h),m:(u.m||f),s:(u.s||f),D:(u.D||f),Q:0,17:f,14:f,l:1h,X:0,18:2s,1w:15,16:f,O:f,1O:f};6.1F=c(){8(6.7.1i)6.1v=6.7.1i;8(6.7.13)6.1u=6.7.13;6.7.Q=a.H(0).E;8(A(a.r(\'B\'))!=\'P\')6.7.k=v(a.r(\'B\'));8(A(a.r(\'N\'))!=\'P\')6.7.N=v(a.r(\'N\'));8(A(a.r(\'m\'))!=\'P\')6.7.m=v(a.r(\'m\'));8(A(a.r(\'s\'))!=\'P\')6.7.s=v(a.r(\'s\'));8(A(a.r(\'D\'))!=\'P\')6.7.D=v(a.r(\'D\'));8(A(a.r(\'18\'))!=\'P\')6.7.18=v(a.r(\'18\'));8(!6.7.m)6.7.m=v(a.o(\'m-R\'));8(!6.7.m)6.7.m=6.7.Q;8(!6.7.s)6.7.s=v(a.o(\'s-R\'));6.7.O=($.t.Z&&$.t.2q<9.5);8(6.7.D){6.7.D=f;6.1t(b)}8(6.7.k){8(6.7.Q==0){a.12(\'M.1M\',6.1L)}z{6.7.k=f;6.1j(b)}}z 6.1c(b);e b};6.1L=c(){6.7.Q=a.H(0).E;8(!6.7.Q)e b;8(!6.7.m)6.7.m=6.7.Q;a.V(\'.1M\');6.7.k=f;6.1j(b);a.U();e b};6.1c=c(w){8(w){8(6.7.14)e f;a.12(($.t.1m?\'M\':\'1I\')+\'.B\',c(j){8(!j.1V||$.1Y(j.1N,[1G,23])==-1)e b;a[j.1N==1G?\'1K\':\'1J\'](f,j);8($.t.Z)a.U();8($.t.1m||$.t.Z)e f;e b});6.7.14=b}z{8(!6.7.14)e f;a.V(($.t.1m?\'M\':\'1I\')+\'.B\');6.7.14=f}};6.1j=c(w){8($.t.Z||w){a.o(\'x\',\'T\');8($.t.Z&&a.r(\'1Q\')&&a.r(\'1Q\').20(\'1T\')==-1)a.o(\'1T\',\'1Z 1W #1X\')}8(w){8(6.7.k)e f;6.1c(f);6.1y();8(6.7.1O){6.y=f;e f}a.o(\'x\',\'T\');a.12(\'M.B\',c(j){8(!a.q())6.S(6.7.m,j);z e 6.S(6.1x(),j)});8(a.q())a.M();$(1g).12(\'1C.B\',c(j){C.7.l.1l(a.1l())});6.7.k=b}z{8(!6.7.k)e f;6.7.l.1z();6.7.l=1h;a.V(\'M.B\');$(1g).V(\'1C.B\');a.o(\'x\',\'k\');6.7.k=f;6.1c(b)}e b};6.1t=c(w){8(w){8(6.7.D)e f;6.7.D=b;a.12(\'U.B\',c(j,1D){8(!6.7.k||1D||!a.q())e b;z e 6.S(6.1x(),j)});a.12(\'1A.B\',c(j){e 6.7.k?6.S(6.7.m,j):b})}z{8(!6.7.D)e f;6.7.D=f;a.V(\'U.B\').V(\'1A.B\');a.M()}};6.S=c(p,j){8(6.7.17)e b;8(!j)j={};6.1H(j);L W=a.o(\'x\');8(6.7.s>0&&p>=6.7.s){p=6.7.s;8(W==\'T\'){a.o(\'x\',\'k\');8(j.1b==\'M\')a.U();8(j.1b==\'U\'&&6.7.N&&6.7.k)a.21(\'U\',b)}}z 8(W==\'k\'&&6.7.k){a.o(\'x\',\'T\');8(j.1b==\'M\')a.U()}8(6.7.m>0&&p<=6.7.m)p=6.7.m;8(p==a.H(0).E){6.7.17=f;e b}e 6.1B(a.H(0).E,p,j,W)};6.1B=c(J,p,j,W){8(!6.7.N||(W==\'k\'&&6.7.k)||j.1b==\'22\'){a.R(p);e 6.1f(j)}6.7.X=1p.2y((6.7.18/6.7.1w)*(p<J?-1:1));6.1o(J,p);e b};6.1o=c(J,p){8(C.7.X==0)e C.1f();C.7.X+=(C.7.X>0?-1:1);8(1p.2p(p-J)<3){a.R(p);e C.1f()}J=C.7.X==0?p:J+1p.2o((p-J)/2);a.R(J);C.7.16=1g.2n(c(){C.1o(J,p)},C.7.1w)};6.1x=c(){L q=a.q();8($.t.1a&&q.2l(-2)=="\\n\\n")q=q.2m(0,q.2r-2)+"\\1S";8($.t.1a)6.7.l.q(\'\');6.7.l.q(q);8(6.7.O)6.7.l.o(\'x\',\'T\').o(\'x\',\'k\');L d=6.7.l.H(0);8(6.7.O)e d.1k+6.7.F;8((d.1d+($.t.1a?1:0))>d.1k){e d.1d+(d.E-d.1k)+6.7.F+($.t.1a?6.7.F:0)}z{8(!a.q())e 6.7.m;z e d.E+6.7.F}};6.1y=c(){8(6.7.l){6.7.l.1z();6.7.l=f}L i=b;L 1e=f;2x(i){6.7.l=a.2w().o({2t:\'2u\',2v:-1R,2k:0,2j:\'T\',1l:a.H(0).24}).r(\'2a\',-1R);8(6.7.O){6.7.l.o({x:\'k\',R:\'k\'});L 19=a.o(\'19\');8((19&&19<4)||1e)6.7.l.o({19:\'27\'})}6.7.l.H(0).y=f;a.13(6.7.l);6.7.l.q(\'\').R(10);6.7.l.q("11");8(6.7.O)6.7.l.o(\'x\',\'T\').o(\'x\',\'k\');L 1U=6.7.l.H(0).1d;6.7.l.q("11\\1S");8(6.7.O)6.7.l.o(\'x\',\'T\').o(\'x\',\'k\');L 1E=6.7.l.H(0).1d;8(!6.7.F){6.7.F=1E-1U;8($.t.Z&&!6.7.O)6.7.F+=6.7.l.H(0).E-6.7.l.R()}8(6.7.O&&6.7.F==0){8(1e)i=f;z{1e=b;6.7.l.1z();26}}z i=f}};6.1H=c(j){6.7.17=b;6.1v(j)};6.1f=c(j){8(6.7.16){1g.2c(6.7.16);6.7.16=f}6.7.17=f;6.1u(j);e b};6.1v=c(){};6.1u=c(){};$(c(){C.1F()})})};$.G.1J=c(Y,j){6.I(c(){8(!6.y||6.7.k)e b;6.S(6.E+(Y?v(Y):6.7.F),j)})};$.G.1K=c(Y,j){6.I(c(){8(!6.y||6.7.k)e b;6.S(6.E-(Y?v(Y):6.7.F),j)})};$.G.2h=c(g){8(g&&g!=b&&g!=f&&g.K()!=\'w\'&&g.K()!=\'1r\')1s(g);8(g&&A(g)==\'1n\')g=g.K()==\'w\'?b:f;6.I(c(){8(!6.y)e b;6.1j(g)})};$.G.2i=c(g){8(g&&g!=b&&g!=f&&g.K()!=\'w\'&&g.K()!=\'1r\')1s(g);8(g&&A(g)==\'1n\')g=g.K()==\'w\'?b:f;6.I(c(){8(!6.y)e b;6.7.N=g})};$.G.1q=c(h){6.I(c(){8(!6.y)e b;6.S(h)})};$.G.2g=c(h){6.I(c(){8(!6.y)e b;h=v(h);8(h<10&&6.7.Q)h=6.7.Q;8(h<10)e b;6.7.m=v(h);8(6.E<6.7.m)$(6).1q(6.7.m)})};$.G.2d=c(h){6.I(c(){8(!6.y)e b;6.7.s=v(h);8(6.E>6.7.s)$(6).1q(6.7.s)})};$.G.29=c(g){8(g&&g!=b&&g!=f&&g.K()!=\'w\'&&g.K()!=\'1r\')1s(g);8(g&&A(g)==\'1n\')g=g.K()==\'w\'?b:f;6.I(c(){8(!6.y)e b;6.1t(g)})};$.G.25=c(){6.I(c(){8(!6.y)e b;6.1y()})}})(28);',62,159,'||||||this|gf|if||txt|true|function||return|false|bool|||event|auto|dummy|min||css|to|val|attr|max|browser|options|parseInt|on|overflow|_growField|else|typeof|autogrow|th|restore|offsetHeight|hOffset|fn|get|each|from|toLowerCase|var|keyup|animate|opera9|undefined|initialH|height|_changeSize|hidden|focus|unbind|ovr|queue|step|opera|||bind|after|keysEnabled||timeout|busy|speed|padding|safari|type|_toggleKeys|scrollHeight|tryPadding|_growAfter|window|null|before|_toggleAuto|clientHeight|width|msie|string|_timeout|Math|growTo|off|delete|_toggleRestore|_growCallbackAfter|_growCallbackBefore|ms|_textHeight|_createDummy|remove|blur|_animate|resize|noChange|s2|_growInit|38|_growBefore|keydown|increase|decrease|_afterShowInit|growinit|keyCode|impossible|offset|style|9999|n11|border|s1|ctrlKey|solid|ccc|inArray|1px|indexOf|trigger|init|40|offsetWidth|growRenewDummy|continue|4px|jQuery|growToggleRestore|tabindex|textarea|clearTimeout|growSetMax|growfield|tagName|growSetMin|growToggleAuto|growToggleAnimation|visibility|top|substr|substring|setTimeout|ceil|abs|version|length|300|position|absolute|left|clone|while|floor'.split('|'),0,{}))


/**
 * 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: 2008/08/26
 *
 * @author Blair Mitchelmore
 * @version 1.0.0
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times, belay) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times, belay);
		});
	},
	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: {
		guid: 1,
		global: {},
		regex: /^([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 = parseInt(result[1], 10);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times, belay) {
			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 (times && times.constructor != Number) {
				belay = !!times;
				times = 0;
			}
			
			times = times || 0;
			belay = belay || false;
			
			if (!element.$timers) 
				element.$timers = {};
			
			if (!element.$timers[label])
				element.$timers[label] = {};
			
			fn.$timerID = fn.$timerID || this.guid++;
			
			var handler = function() {
				if (belay && this.inProgress) 
					return;
				this.inProgress = true;
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
				this.inProgress = false;
			};
			
			handler.$timerID = fn.$timerID;
			
			if (!element.$timers[label][fn.$timerID]) 
				element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);
			
			if ( !this.global[label] )
				this.global[label] = [];
			this.global[label].push( element );
			
		},
		remove: function(element, label, fn) {
			var timers = element.$timers, 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 ) 
					element.$timers = null;
			}
		}
	}
});


(function($){

	$.tooltip = {
		/* Default tooltip settings */
		defaults: {
			'class': 'tooltip',			// Tooltip class added to destiny HTML element
			css: {},					// CSS applied to destiny HTML element
			event: 'mouseover',			// Event the tooltip must respond to
			smart: false,				// If the tooltip content is generated in a 'smart' way
			track: true,				// If the tooltip must follow mouse position
		
			offset: {x: 12, y: 18}		// Offset from current mouse position, only applied if track set to true
			
		},

		/* 
		 * Shortcut to setup default settings
		 * Example:
		 *		$.tooltip.setup({event: 'click', track: 'false'});
		 */
		setup: function(opt){ $.extend($.tooltip.defaults, opt) }
	}

	/* The TIP object */
	var tip = function(src, opt) {
		var self = this;
		var html = '';
		src = $(src);

		/* Use metadata plugin (if loaded) to modify local options */
		if($.metadata) { opt = $.extend({}, opt, src.metadata().tooltip) }

		/* Tries to generate the content from the HTML element attributes */
		if(opt.smart) {
			/* Tooltip title from 'title' attribute */
			if(!opt.title){ opt.title = src.attr('title') }
			/* Tooltip text from 'alt' attribute */
			if(!opt.text){ opt.text = src.attr('alt') }
			/* url from 'href' attributes. Great for link tags */
			if(!opt.href){ opt.href = src.attr('href') }
		}

		/* Generates HTML content */
		var html = '';
		html += '<div class="tt_text">'+opt.text+'</div>' ;
		/* If no content where generated, no tooltip is created */
		if(html == ''){ delete this; return }
		
		/* Removes attributes disabling default tooltips from the browser */
		src
			.removeAttr('title')
			.removeAttr('alt')

		$.data(src, 'tooltip', self)
		self.dst = opt.dst;

		src
			.bind(opt.event+'.tooltip', over)
			.bind('mouseout.tooltip', out)
			.bind('focus.tooltip', over)
			.bind('blur.tooltip', out)
			.bind('click.tooltip', hide)

		/* Destroy existent timers */
		function destroy_timers() {
			if(self.timein){
				clearTimeout(self.timein);
				delete self.timein
			}
			if(self.timeout){
				clearTimeout(self.timeout);
				delete self.timeout
			}
		}

		/* Called when the 'show tooltip' event is raised */
		function over(ev){
			destroy_timers();
			if(self.st == out){ return }
			self.st = over;
			/* No destiny defined, must create a new HTML element */
			if(!self.dst) {
				self.dst = $('<div>')
					.appendTo(document.body)
					.hide(0);
			}
			self.ev = ev;
			/* Wait some time and show the tooltip */
			self.timein = setTimeout(show, 600)
		}

		/* Shows the tooltip */
		function show(){
			destroy_timers();
			/* No destiny, no showing */
			if(!self.dst) { return }
			/* Modifies tooltip CSS and content */
			self.dst
				.addClass(opt['class'])
				.css(opt.css)
				.html(html);
			/* If a duration is defined */
			if(opt.duration > 0) {
				self.timein = setTimeout(hide, opt.duration)
			}
			/* Keep track of mouse position if 'track' is activated */
			if(opt.track) {
				//alert(self.dst.html());
				self.dst
					.css({
						position:'absolute'
						
					}).fadeIn('slow');
				src
					.bind('mousemove.tooltip', move);
				$('body')
					.bind('click.tooltip', hide)
			}

			/* Calculates width and height */
			self.w = self.dst.width();
			self.h = self.dst.height();
			/* 'on show' callback */
			if(opt.onshow){ opt.onshow.apply(self.dst) }
			if(opt.track){ move() }
		}

		/* Called when the tooltip must hide */
		function out(){
			destroy_timers();
			if(self.st != over){ return }
			/* Wait some time and hides the tooltip */
			self.timeout = setTimeout(hide, opt['out'] || 0)
		}

		/* Hides the tooltip */
		function hide() {
			destroy_timers();
			/* Unbind all events in body from the tooltip namespace */
			$('body').unbind('.tooltip');
			/* Unbind mousemove events */
			$('src').unbind('mousemove.tooltip');
			/* No destiny, no hiding */
			if(!self.dst) { return }
			/* Clear destiny contents */
			self.dst.empty();
			/* 'on hide' callback */
			if(opt.onhide){ opt.onhide.apply(self.dst) }
			/* If destiny was dinamicly created, destroy it */
			if(self.dst != opt.dst) {
				self.dst.remove();
				delete self.dst
			}
		}

		/* Moves the tooltip to follow the cursor */
		function move(ev){
			if(!ev){ ev = self.ev } else { self.ev = ev}
			if(!self.dst) { return }
			var p = {
				x: ev.pageX + opt.offset.x, y: ev.pageY + opt.offset.y,
				w: self.w, h: self.h
			}
			w = window;
			var v = {
				x: w.scrollX, y: w.scrollY,
				w: w.innerWidth - 20/*(w.scrollMaxY > 0 ? 30 : 20)*/,
				h: w.innerHeight - 20/*(w.scrollMaxX > 0 ? 20 : 10)*/
			};
			/* Better not to go offscreen */
			if(p.x + p.w > v.x + v.w) { p.x = v.x + v.w - p.w }
			if(p.y + p.h > v.y + v.h) { p.y = ev.pageY - p.h - opt.offset.y }
			if(p.x < v.x){ p.x = v.x }
			if(p.y < v.y){ p.y = v.y }
			self.dst.css({top:p.y, left:p.x})
		}
	}

	/* 
	 * Change tooltip local settings
	 * Example:
	 * 		$('a').tooltip('setup', {event: 'click'})
	 */
	function	setup(){
		return this.each(function(){
			t = $.data(this, 'tooltip');
			if(t){$.extend(t.opt, opt)}
			return this
		})
	}

	/* 
	 * Removes tooltip
	 * Example:
	 * 		$('div').tooltip('remove')
	 */
	function	remove(){
		return
			this
				.unbind('.tooltip')
				.removeData('tooltip')
	}

	/* 
	 * Creates a tooltip
	 * Example:
	 * 		$('div').tooltip('create')
	 */
	function	create(opt){
		remove.apply(this);
		opt = $.extend({}, $.tooltip.defaults, opt);
		return this.each(function(){
			new tip(this, opt);
		});
	}

	/*
	 * Extends jQuery functions
	 */
	$.fn.tooltip = function(a, o) {
		/* If called with only one non-string parameter (or none), it assumes 'create' by default */
		if(!o && (typeof a != 'string')) {
			o = a;
			a = 'create'
		}
		/* Call the selected function */
		return (f = ({
			setup: setup,
			remove: remove,
			create: create
		})[a]) && f.apply(this, [o])
	}

})(jQuery);

/**
 * Flash (http://jquery.lukelutman.com/plugins/flash)
 * A jQuery plugin for embedding Flash movies.
 * 
 * Version 1.0
 * November 9th, 2006
 *
 * Copyright (c) 2006 Luke Lutman (http://www.lukelutman.com)
 * Dual licensed under the MIT and GPL licenses.
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.opensource.org/licenses/gpl-license.php
 * 
 * Inspired by:
 * SWFObject (http://blog.deconcept.com/swfobject/)
 * UFO (http://www.bobbyvandersluis.com/ufo/)
 * sIFR (http://www.mikeindustries.com/sifr/)
 * 
 * IMPORTANT: 
 * The packed version of jQuery breaks ActiveX control
 * activation in Internet Explorer. Use JSMin to minifiy
 * jQuery (see: http://jquery.lukelutman.com/plugins/flash#activex).
 *
 **/ 
;(function(){
	
var $$;

/**
 * 
 * @desc Replace matching elements with a flash movie.
 * @author Luke Lutman
 * @version 1.0.1
 *
 * @name flash
 * @param Hash htmlOptions Options for the embed/object tag.
 * @param Hash pluginOptions Options for detecting/updating the Flash plugin (optional).
 * @param Function replace Custom block called for each matched element if flash is installed (optional).
 * @param Function update Custom block called for each matched if flash isn't installed (optional).
 * @type jQuery
 *
 * @cat plugins/flash
 * 
 * @example $('#hello').flash({ src: 'hello.swf' });
 * @desc Embed a Flash movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { version: 8 });
 * @desc Embed a Flash 8 movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { expressInstall: true });
 * @desc Embed a Flash movie using Express Install if flash isn't installed.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { update: false });
 * @desc Embed a Flash movie, don't show an update message if Flash isn't installed.
 *
**/
$$ = jQuery.fn.flash = function(htmlOptions, pluginOptions, replace, update) {
	
	// Set the default block.
	var block = replace || $$.replace;
	
	// Merge the default and passed plugin options.
	pluginOptions = $$.copy($$.pluginOptions, pluginOptions);
	
	// Detect Flash.
	if(!$$.hasFlash(pluginOptions.version)) {
		// Use Express Install (if specified and Flash plugin 6,0,65 or higher is installed).
		if(pluginOptions.expressInstall && $$.hasFlash(6,0,65)) {
			// Add the necessary flashvars (merged later).
			var expressInstallOptions = {
				flashvars: {  	
					MMredirectURL: location,
					MMplayerType: 'PlugIn',
					MMdoctitle: jQuery('title').text() 
				}					
			};
		// Ask the user to update (if specified).
		} else if (pluginOptions.update) {
			// Change the block to insert the update message instead of the flash movie.
			block = update || $$.update;
		// Fail
		} else {
			// The required version of flash isn't installed.
			// Express Install is turned off, or flash 6,0,65 isn't installed.
			// Update is turned off.
			// Return without doing anything.
			return this;
		}
	}
	
	// Merge the default, express install and passed html options.
	htmlOptions = $$.copy($$.htmlOptions, expressInstallOptions, htmlOptions);
	
	// Invoke $block (with a copy of the merged html options) for each element.
	return this.each(function(){
		block.call(this, $$.copy(htmlOptions));
	});
	
};
/**
 *
 * @name flash.copy
 * @desc Copy an arbitrary number of objects into a new object.
 * @type Object
 * 
 * @example $$.copy({ foo: 1 }, { bar: 2 });
 * @result { foo: 1, bar: 2 };
 *
**/
$$.copy = function() {
	var options = {}, flashvars = {};
	for(var i = 0; i < arguments.length; i++) {
		var arg = arguments[i];
		if(arg == undefined) continue;
		jQuery.extend(options, arg);
		// don't clobber one flash vars object with another
		// merge them instead
		if(arg.flashvars == undefined) continue;
		jQuery.extend(flashvars, arg.flashvars);
	}
	options.flashvars = flashvars;
	return options;
};
/*
 * @name flash.hasFlash
 * @desc Check if a specific version of the Flash plugin is installed
 * @type Boolean
 *
**/
$$.hasFlash = function() {
	// look for a flag in the query string to bypass flash detection
	if(/hasFlash\=true/.test(location)) return true;
	if(/hasFlash\=false/.test(location)) return false;
	var pv = $$.hasFlash.playerVersion().match(/\d+/g);
	var rv = String([arguments[0], arguments[1], arguments[2]]).match(/\d+/g) || String($$.pluginOptions.version).match(/\d+/g);
	for(var i = 0; i < 3; i++) {
		pv[i] = parseInt(pv[i] || 0);
		rv[i] = parseInt(rv[i] || 0);
		// player is less than required
		if(pv[i] < rv[i]) return false;
		// player is greater than required
		if(pv[i] > rv[i]) return true;
	}
	// major version, minor version and revision match exactly
	return true;
};
/**
 *
 * @name flash.hasFlash.playerVersion
 * @desc Get the version of the installed Flash plugin.
 * @type String
 *
**/
$$.hasFlash.playerVersion = function() {
	// ie
	try {
		try {
			// avoid fp6 minor version lookup issues
			// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
			var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
			try { axo.AllowScriptAccess = 'always';	} 
			catch(e) { return '6,0,0'; }				
		} catch(e) {}
		return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
	// other browsers
	} catch(e) {
		try {
			if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
				return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
			}
		} catch(e) {}		
	}
	return '0,0,0';
};
/**
 *
 * @name flash.htmlOptions
 * @desc The default set of options for the object or embed tag.
 *
**/
$$.htmlOptions = {
	height: 240,
	flashvars: {},
	pluginspage: 'http://www.adobe.com/go/getflashplayer',
	src: '#',
	type: 'application/x-shockwave-flash',
	width: 320		
};
/**
 *
 * @name flash.pluginOptions
 * @desc The default set of options for checking/updating the flash Plugin.
 *
**/
$$.pluginOptions = {
	expressInstall: false,
	update: true,
	version: '6.0.65'
};
/**
 *
 * @name flash.replace
 * @desc The default method for replacing an element with a Flash movie.
 *
**/
$$.replace = function(htmlOptions) {
	this.innerHTML = '<div class="alt">'+this.innerHTML+'</div>';
	jQuery(this)
		.addClass('flash-replaced')
		.prepend($$.transform(htmlOptions));
};
/**
 *
 * @name flash.update
 * @desc The default method for replacing an element with an update message.
 *
**/
$$.update = function(htmlOptions) {
	var url = String(location).split('?');
	url.splice(1,0,'?hasFlash=true&');
	url = url.join('');
	var msg = '<p>This content requires the Flash Player. <a href="http://www.adobe.com/go/getflashplayer">Download Flash Player</a>. Already have Flash Player? <a href="'+url+'">Click here.</a></p>';
	this.innerHTML = '<span class="alt">'+this.innerHTML+'</span>';
	jQuery(this)
		.addClass('flash-update')
		.prepend(msg);
};
/**
 *
 * @desc Convert a hash of html options to a string of attributes, using Function.apply(). 
 * @example toAttributeString.apply(htmlOptions)
 * @result foo="bar" foo="bar"
 *
**/
function toAttributeString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'="'+this[key]+'" ';
	return s;		
};
/**
 *
 * @desc Convert a hash of flashvars to a url-encoded string, using Function.apply(). 
 * @example toFlashvarsString.apply(flashvarsObject)
 * @result foo=bar&foo=bar
 *
**/
function toFlashvarsString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'='+encodeURIComponent(this[key])+'&';
	return s.replace(/&$/, '');		
};
/**
 *
 * @name flash.transform
 * @desc Transform a set of html options into an embed tag.
 * @type String 
 *
 * @example $$.transform(htmlOptions)
 * @result <embed src="foo.swf" ... />
 *
 * Note: The embed tag is NOT standards-compliant, but it 
 * works in all current browsers. flash.transform can be
 * overwritten with a custom function to generate more 
 * standards-compliant markup.
 *
**/
$$.transform = function(htmlOptions) {
	htmlOptions.toString = toAttributeString;
	if(htmlOptions.flashvars) htmlOptions.flashvars.toString = toFlashvarsString;
	return '<embed ' + String(htmlOptions) + ' wmode="transparent"/>';		
};

/**
 *
 * Flash Player 9 Fix (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
 *
**/
if (window.attachEvent) {
	window.attachEvent("onbeforeunload", function(){
		__flash_unloadHandler = function() {};
		__flash_savedUnloadHandler = function() {};
	});
}
	
})();






/**
 * jCarouselLite - jQuery plugin to navigate images/any content in a carousel style widget.
 * @requires jQuery v1.2 or above
 *
 * http://gmarwaha.com/jquery/jcarousellite/
 *
 * Copyright (c) 2007 Ganeshji Marwaha (gmarwaha.com)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 1.0.1
 * Note: Requires jquery 1.2 or above from version 1.0.1
 */

/**
 * Creates a carousel-style navigation widget for images/any-content from a simple HTML markup.
 *
 * The HTML markup that is used to build the carousel can be as simple as...
 *
 *  <div class="carousel">
 *      <ul>
 *          <li><img src="image/1.jpg" alt="1"></li>
 *          <li><img src="image/2.jpg" alt="2"></li>
 *          <li><img src="image/3.jpg" alt="3"></li>
 *      </ul>
 *  </div>
 *
 * As you can see, this snippet is nothing but a simple div containing an unordered list of images.
 * You don't need any special "class" attribute, or a special "css" file for this plugin.
 * I am using a class attribute just for the sake of explanation here.
 *
 * To navigate the elements of the carousel, you need some kind of navigation buttons.
 * For example, you will need a "previous" button to go backward, and a "next" button to go forward.
 * This need not be part of the carousel "div" itself. It can be any element in your page.
 * Lets assume that the following elements in your document can be used as next, and prev buttons...
 *
 * <button class="prev">&lt;&lt;</button>
 * <button class="next">&gt;&gt;</button>
 *
 * Now, all you need to do is call the carousel component on the div element that represents it, and pass in the
 * navigation buttons as options.
 *
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev"
 * });
 *
 * That's it, you would have now converted your raw div, into a magnificient carousel.
 *
 * There are quite a few other options that you can use to customize it though.
 * Each will be explained with an example below.
 *
 * @param an options object - You can specify all the options shown below as an options object param.
 *
 * @option btnPrev, btnNext : string - no defaults
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev"
 * });
 * @desc Creates a basic carousel. Clicking "btnPrev" navigates backwards and "btnNext" navigates forward.
 *
 * @option btnGo - array - no defaults
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      btnGo: [".0", ".1", ".2"]
 * });
 * @desc If you don't want next and previous buttons for navigation, instead you prefer custom navigation based on
 * the item number within the carousel, you can use this option. Just supply an array of selectors for each element
 * in the carousel. The index of the array represents the index of the element. What i mean is, if the
 * first element in the array is ".0", it means that when the element represented by ".0" is clicked, the carousel
 * will slide to the first element and so on and so forth. This feature is very powerful. For example, i made a tabbed
 * interface out of it by making my navigation elements styled like tabs in css. As the carousel is capable of holding
 * any content, not just images, you can have a very simple tabbed navigation in minutes without using any other plugin.
 * The best part is that, the tab will "slide" based on the provided effect. :-)
 *
 * @option mouseWheel : boolean - default is false
 * @example
 * $(".carousel").jCarouselLite({
 *      mouseWheel: true
 * });
 * @desc The carousel can also be navigated using the mouse wheel interface of a scroll mouse instead of using buttons.
 * To get this feature working, you have to do 2 things. First, you have to include the mouse-wheel plugin from brandon.
 * Second, you will have to set the option "mouseWheel" to true. That's it, now you will be able to navigate your carousel
 * using the mouse wheel. Using buttons and mouseWheel or not mutually exclusive. You can still have buttons for navigation
 * as well. They complement each other. To use both together, just supply the options required for both as shown below.
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      mouseWheel: true
 * });
 *
 * @option auto : number - default is null, meaning autoscroll is disabled by default
 * @example
 * $(".carousel").jCarouselLite({
 *      auto: 800,
 *      speed: 500
 * });
 * @desc You can make your carousel auto-navigate itself by specfying a millisecond value in this option.
 * The value you specify is the amount of time between 2 slides. The default is null, and that disables auto scrolling.
 * Specify this value and magically your carousel will start auto scrolling.
 *
 * @option speed : number - 200 is default
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      speed: 800
 * });
 * @desc Specifying a speed will slow-down or speed-up the sliding speed of your carousel. Try it out with
 * different speeds like 800, 600, 1500 etc. Providing 0, will remove the slide effect.
 *
 * @option easing : string - no easing effects by default.
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      easing: "bounceout"
 * });
 * @desc You can specify any easing effect. Note: You need easing plugin for that. Once specified,
 * the carousel will slide based on the provided easing effect.
 *
 * @option vertical : boolean - default is false
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      vertical: true
 * });
 * @desc Determines the direction of the carousel. true, means the carousel will display vertically. The next and
 * prev buttons will slide the items vertically as well. The default is false, which means that the carousel will
 * display horizontally. The next and prev items will slide the items from left-right in this case.
 *
 * @option circular : boolean - default is true
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      circular: false
 * });
 * @desc Setting it to true enables circular navigation. This means, if you click "next" after you reach the last
 * element, you will automatically slide to the first element and vice versa. If you set circular to false, then
 * if you click on the "next" button after you reach the last element, you will stay in the last element itself
 * and similarly for "previous" button and first element.
 *
 * @option visible : number - default is 3
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      visible: 4
 * });
 * @desc This specifies the number of items visible at all times within the carousel. The default is 3.
 * You are even free to experiment with real numbers. Eg: "3.5" will have 3 items fully visible and the
 * last item half visible. This gives you the effect of showing the user that there are more images to the right.
 *
 * @option start : number - default is 0
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      start: 2
 * });
 * @desc You can specify from which item the carousel should start. Remember, the first item in the carousel
 * has a start of 0, and so on.
 *
 * @option scrool : number - default is 1
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      scroll: 2
 * });
 * @desc The number of items that should scroll/slide when you click the next/prev navigation buttons. By
 * default, only one item is scrolled, but you may set it to any number. Eg: setting it to "2" will scroll
 * 2 items when you click the next or previous buttons.
 *
 * @option beforeStart, afterEnd : function - callbacks
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      beforeStart: function(a) {
 *          alert("Before animation starts:" + a);
 *      },
 *      afterEnd: function(a) {
 *          alert("After animation ends:" + a);
 *      }
 * });
 * @desc If you wanted to do some logic in your page before the slide starts and after the slide ends, you can
 * register these 2 callbacks. The functions will be passed an argument that represents an array of elements that
 * are visible at the time of callback.
 *
 *
 * @cat Plugins/Image Gallery
 * @author Ganeshji Marwaha/ganeshread@gmail.com
 */

(function($) {                                          // Compliant with jquery.noConflict()
$.fn.jCarouselLite = function(o) {
    o = $.extend({
        btnPrev: null,
        btnNext: null,
        btnGo: null,
        mouseWheel: false,
        auto: null,

        speed: 800,
        easing: null,

        vertical: false,
        circular: true,
        visible: 4,
        start: 0,
        scroll: 1,

        beforeStart: null,
        afterEnd: null
    }, o || {});

    return this.each(function() {                           // Returns the element collection. Chainable.

        var running = false, animCss=o.vertical?"top":"left", sizeCss=o.vertical?"height":"width";
        var div = $(this), ul = $("ul", div), tLi = $("li", ul), tl = tLi.size(), v = o.visible;


        if(o.circular) {
            ul.prepend(tLi.slice(tl-v-1+1).clone())
              .append(tLi.slice(0,v).clone());
            o.start += v;
        }

        var li = $("li", ul), itemLength = li.size(), curr = o.start;
        div.css("visibility", "visible");

        li.css({overflow: "hidden", float: o.vertical ? "none" : "left"});
        ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"});
        div.css({overflow: "hidden", position: "relative", "z-index": "2", left: "0px"});

        var liSize = o.vertical ? height(li) : width(li);   // Full li size(incl margin)-Used for animation
        var ulSize = liSize * itemLength;                   // size of full ul(total length, not just for the visible items)
        var divSize = liSize * v;                           // size of entire div(total length for just the visible items)

        li.css({width: li.width(), height: li.height()});
        ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize));

        div.css(sizeCss, divSize+"px");                     // Width of the DIV. length of visible images

        if(o.btnPrev)
            $(o.btnPrev).click(function() {
                return go(curr-o.scroll);
            });

        if(o.btnNext)
            $(o.btnNext).click(function() {
                return go(curr+o.scroll);
            });

        if(o.btnGo)
            $.each(o.btnGo, function(i, val) {
                $(val).click(function() {
                    return go(o.circular ? o.visible+i : i);
                });
            });

        if(o.mouseWheel && div.mousewheel)
            div.mousewheel(function(e, d) {
                return d>0 ? go(curr-o.scroll) : go(curr+o.scroll);
            });

        if(o.auto)
            setInterval(function() {
                go(curr+o.scroll);
            }, o.auto+o.speed);

        function vis() {
            return li.slice(curr).slice(0,v);
        };

        function go(to) {
            if(!running) {

                if(o.beforeStart)
                    o.beforeStart.call(this, vis());

                if(o.circular) {            // If circular we are in first or last, then goto the other end
                    if(to<=o.start-v-1) {           // If first, then goto last
                        ul.css(animCss, -((itemLength-(v*2))*liSize)+"px");
                        // If "scroll" > 1, then the "to" might not be equal to the condition; it can be lesser depending on the number of elements.
                        curr = to==o.start-v-1 ? itemLength-(v*2)-1 : itemLength-(v*2)-o.scroll;
                    } else if(to>=itemLength-v+1) { // If last, then goto first
                        ul.css(animCss, -( (v) * liSize ) + "px" );
                        // If "scroll" > 1, then the "to" might not be equal to the condition; it can be greater depending on the number of elements.
                        curr = to==itemLength-v+1 ? v+1 : v+o.scroll;
                    } else curr = to;
                } else {                    // If non-circular and to points to first or last, we just return.
                    if(to<0 || to>itemLength-v) return;
                    else curr = to;
                }                           // If neither overrides it, the curr will still be "to" and we can proceed.

                running = true;

                ul.animate(
                    animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing,
                    function() {
                        if(o.afterEnd)
                            o.afterEnd.call(this, vis());
                        running = false;
                    }
                );
                // Disable buttons when the carousel reaches the last/first, and enable when not
                if(!o.circular) {
                    $(o.btnPrev + "," + o.btnNext).removeClass("disabled");
                    $( (curr-o.scroll<0 && o.btnPrev)
                        ||
                       (curr+o.scroll > itemLength-v && o.btnNext)
                        ||
                       []
                     ).addClass("disabled");
                }

            }
            return false;
        };
    });
};

function css(el, prop) {
    return parseInt($.css(el[0], prop)) || 0;
};
function width(el) {
    return  el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
};
function height(el) {
    return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
};

})(jQuery);


//jMaps

/**
 * @classDescription The Mapifies variable is the main class object for jMaps
 */
var Mapifies;

if (!Mapifies) Mapifies = {};

/**
 * The main object that holds the maps
 */
Mapifies.MapObjects = {};

/**
 * Creates a new map on the passed element with the defined options.  Creates a global object that contains the map.
 * @method
 * @namespace Mapifies.MapObjects
 * @id Mapifies.MapObjects.Set
 * @alias Mapifies.MapObjects.Set
 * @param {jQuery} element The element that contains the map.
 * @param {Object} options An object that contains the options.
 * @return {Object} The object that contains the map.
 */
Mapifies.MapObjects.Set = function ( element, options ) {
	var mapName = jQuery(element).attr('id');
	var thisMap = new GMap2(element);
	Mapifies.MapObjects[mapName] = thisMap;
	Mapifies.MapObjects[mapName].Options = options;
	return Mapifies.MapObjects[mapName];
};

/**
 * Adds additional objects and functions to an existing MapObject
 * @method
 * @namespace Mapifies.MapObjects
 * @id Mapifies.MapObjects.Append
 * @alias Mapifies.MapObjects.Append
 * @param {jQuery} element The element that contains the map
 * @param {Object} description The name of the object to create
 * @param {Object} appending The object or function to append
 */
Mapifies.MapObjects.Append = function ( element, description, appending ) {
	var mapName = jQuery(element).attr('id');
	Mapifies.MapObjects[mapName][description] = appending;
};

/**
 * Returns the current map object for the passed element
 * @method
 * @namespace Mapifies.MapObjects
 * @id Mapifies.MapObjects.Get
 * @alias Mapifies.MapObjects.Get
 * @param {jQuery} element The element that contains the map.
 * @return {Object} Mapifies The Mapifies object that contains the map.
 */
Mapifies.MapObjects.Get = function ( element ) {
	return Mapifies.MapObjects[jQuery(element).attr('id')];
};

/**
 * The main function to initialise the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.Initialise
 * @alias Mapifies.Initialise
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Object} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the map object and options.
 */
Mapifies.Initialise = function ( element, options, callback ) {
	/**
	 * Default options for Initialise
	 * @method
	 * @namespace Mapifies.Initialise
	 * @id Mapifies.Initialise.defaults
	 * @alias Mapifies.Initialise.defaults
	 * @param {String} language The locale language for the map
	 * @param {String} mapType The type of map to create.  Options are 'map' (default), 'sat' and 'hybrid'.
	 * @param {Object} mapCenter An array that contains the Lat/Lng coordinates of the map center.
	 * @param {Number} mapZoom The initial zoom level of the map.
	 * @param {String} mapControl The option for the map control.  The options are 'small' (default), 'large' or 'none'
	 * @param {Boolean} mapEnableType Defines if the buttons for map type are shown.  Default false.
	 * @param {Boolean} mapEnableOverview Defines if the map overview is shown.  Default false.
	 * @param {Boolean} mapEnableDragging Defines if the map is draggable or not.  Default true.
	 * @param {Boolean} mapEnableInfoWindows Defines if info windows are shown on the map or not.  Default true.
	 * @param {Boolean} mapEnableDoubleClickZoom Defines if double clicking zooms the map.  Default false.
	 * @param {Boolean} mapEnableSmoothZoom Defines if smooth scrolling is enabled.  Default false.
	 * @param {Boolean} mapEnableGoogleBar Defines if the google map search tool is enabled.  Default false.
	 * @param {Boolean} mapEnableScaleControl Defines if the scale bar is shown.  Default false.
	 * @param {Boolean} mapShowjMapsIcon Defines if the jMaps icon is shown.  Default true.
	 * @param {Boolean} debugMode Defines if the map object created is returned to the Firebug console.  Default false.
	 * @return {Object} The options for SearchAddress
	 */
	function defaults() {
		return {
			// Initial type of map to display
			'language': 'pl',
			// Options: "map", "sat", "hybrid"
			'mapType': 'map',
			// Initial map center
			'mapCenter': [55.958858,-3.162302],
			// Initial zoom level
			'mapZoom': 12,
			// Initial map control size
			// Options: "large", "small", "none"
			'mapControl': 'small',
			// Initialise type of map control
			'mapEnableType': false,
			// Initialise small map overview
			'mapEnableOverview': false,
			// Enable map dragging when left button held down
			'mapEnableDragging': true,
			// Enable map info windows
			'mapEnableInfoWindows': true,
			// Enable double click zooming
			'mapEnableDoubleClickZoom': false,
			// Enable zooming with scroll wheel
			'mapEnableScrollZoom': false,
			// Enable smooth zoom
			'mapEnableSmoothZoom': false,
			// Enable Google Bar
			'mapEnableGoogleBar': false,
			// Enables scale bar
			'mapEnableScaleControl': false,
			// Enable the Mapifies icon
			'mapShowjMapsIcon': false,
			//Debug Mode
			'debugMode': false
		};
	};
	options = jQuery.extend(defaults(), options);
	
	if (GBrowserIsCompatible()) {
			
		var thisMap = Mapifies.MapObjects.Set(element, options);
		var mapType = Mapifies.GetMapType(options.mapType);
		thisMap.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]), options.mapZoom, mapType);
		
		
		// Attach a controller to the map view
		// Will attach a large or small.  If any other value passed (i.e. "none") it is ignored
		switch (options.mapControl) {
			case "small":
				thisMap.addControl(new GSmallMapControl());
				break;
			case "large":
				thisMap.addControl(new GLargeMapControl());
				break;
		};
		// Type of map Control (Map,Sat,Hyb)
		if (options.mapEnableType) 
			thisMap.addControl(new GMapTypeControl()); // Off by default
		// Show the small overview map
		if (options.mapEnableOverview) 
			thisMap.addControl(new GOverviewMapControl());// Off by default
		// GMap2 Functions (in order of the docs for clarity)
		// Enable a mouse-dragable map
		if (!options.mapEnableDragging) 
			thisMap.disableDragging(); // On by default
		// Enable Info Windows
		if (!options.mapEnableInfoWindows) 
			thisMap.disableInfoWindow(); // On by default
		// Enable double click zoom on the map
		if (options.mapEnableDoubleClickZoom) 
			thisMap.enableDoubleClickZoom(); // On by default
		// Enable scrollwheel on the map
		if (options.mapEnableScrollZoom) 
			thisMap.enableScrollWheelZoom(); //Off by default
		// Enable smooth zooming
		if (options.mapEnableSmoothZoom) 
			thisMap.enableContinuousZoom(); // Off by default
		// Enable Google Bar
		if (options.mapEnableGoogleBar) 
			thisMap.enableGoogleBar(); //Off by default
		// Enables Scale bar
		if (options.mapEnableScaleControl) 
			thisMap.addControl(new GScaleControl());
		
		if (options.debugMode) 
			console.log(Mapifies);
		
		if (typeof callback == 'function') 
			return callback(thisMap, element, options);
	} else {
		jQuery(element).text('Your browser does not support Google Maps.');
		return false;
	}
	return;
};

/**
 * A function to move a map to a passed position
 * @method
 * @namespace Mapifies
 * @id Mapifies.MoveTo
 * @alias Mapifies.MoveTo
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Object} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the map object and options or true.
 */
Mapifies.MoveTo = function ( element, options, callback ) {
	/**
 	 * Default options for MoveTo
   * @method
   * @namespace Mapifies
   * @id Mapifies.MoveTo
   * @alias Mapifies.MoveTo
   * @param {String} centerMethod The element to initialise the map on.
   * @param {String} mapType The type of map to create.  Options are 'map' (default), 'sat' and 'hybrid'.
   * @param {Object} mapCenter An array that contains the Lat/Lng coordinates of the map center.
   * @param {Number} mapZoom The initial zoom level of the map.
   * @return {Function} callback The callback option with the point object and options or true.
   */	
	function defaults() {
		return {
			'centerMethod': 'normal',
			'mapType': null,
			'mapCenter': [],
			'mapZoom': null,
			'mapPoint': null
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);	
	if (options.mapType)
		var mapType = Mapifies.GetMapType(options.mapType);
	if(options.mapPoint) var point=options.mapPoint;
	else var point = new GLatLng(options.mapCenter[0], options.mapCenter[1]);
	
	switch (options.centerMethod) {
		case 'normal':
			thisMap.setCenter(point, options.mapZoom, mapType);
		break;
		case 'pan':
			thisMap.panTo(point);
		break;
	}
	if (typeof callback == 'function') return callback(point, options);
};

/**
 * Save your current position on the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.SavePosition
 * @alias Mapifies.SavePosition
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Object} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the map object and options or true.
 */
Mapifies.SavePosition = function( element, options, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.savePosition();
	if (typeof callback == 'function') return callback(thisMap);
};

/**
 * Goto a previously saved position
 * @method
 * @namespace Mapifies
 * @id Mapifies.GotoSavedPosition
 * @alias Mapifies.GotoSavedPosition
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the map object and options or true.
 */
Mapifies.GotoSavedPosition = function ( element, options, callback) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.returnToSavedPosition();
	if (typeof callback == 'function') return callback(thisMap);
};

/**
 * Create a keyboard handler to handle keyboard navigation
 * @method
 * @namespace Mapifies
 * @id Mapifies.CreateKeyboardHandler
 * @alias Mapifies.CreateKeyboardHandler
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Object} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the keyboard handler.
 */
Mapifies.CreateKeyboardHandler = function( element, options, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	var keyboardHandler = new GKeyboardHandler(thisMap);
	if (typeof callback == 'function') return callback(keyboardHandler);
};

/**
 * Check if a map container element has been resized or toggled from show/hide (Added r68)
 * @method
 * @namespace Mapifies
 * @id Mapifies.CheckResize
 * @alias Mapifies.CheckResize
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Object} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the map object handler.
 */
Mapifies.CheckResize = function( element, options, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.checkResize();
	if (typeof callback == 'function') return callback(element);
};

/**
 * The SearchAddress function takes a map, options and callback function.  The options can contain either an address string, to which a point is returned - or reverse geocoding a GLatLng, where an address is returned
 * @method
 * @namespace Mapifies
 * @id Mapifies.SearchAddress
 * @param {jQuery} element The jQuery object containing the map element.
 * @param {Object} options An object of options
 * @param {Function} callback The callback function that returns the result
 * @return {Function} Returns a passed callback function or true if no callback specified
 */
Mapifies.SearchAddress = function( element, options, callback) {
	/**
	 * Default options for SearchAddress
	 * @method
	 * @namespace Mapifies.SearchAddress
	 * @id Mapifies.SearchAddress.defaults
	 * @alias Mapifies.SearchAddress.defaults
	 * @param {String} query The Address or GLatLng to query in the geocoder
	 * @param {String} returnType The type of value you want to return from Google.  This is mapped to the function names available, the options are 'getLatLng' which returns coordinates, and 'getLocations' which returns points.
	 * @param {GGeoCache} cache The GGeoCache to store the results in if required
	 * @param {String} countryCode The country code to localise results
	 * @return {Object} The options for SearchAddress
	 */
	function defaults() {
		return {
			// Address to search for
			'query': null,
			// Return Type
			'returnType': 'getLatLng',
			// Optional Cache to store Geocode Data (not implemented yet)
			'cache': undefined,
			// Country code for localisation (not implemented yet)
			'countryCode': 'pl',
			'update': false
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	
	// Check to see if the Geocoder already exists in the object
	// or create a temporary locally scoped one.
	if (typeof thisMap.Geocoder === 'undefined') {	
		if (typeof options.cache === 'undefined') {
		 	var geoCoder = new GClientGeocoder();
		} else {
			var geoCoder = new GClientGeocoder(cache);
		}
		Mapifies.MapObjects.Append(element, 'Geocoder', geoCoder);
		// We need to get the map object again, now we have attached the geocoder
		thisMap = Mapifies.MapObjects.Get(element);
	}
	thisMap.Geocoder[options.returnType](options.query, function(result){
		if (typeof callback === 'function') {
			return callback(result, options); 
		}
	});
	if(options.update) page.send({ 'command':'find_city', 'data':{'city': options.query}});
	return;
};
	
/**
 * The SearchDirections function allows you to search for directions between two or more points and return it to a map and a directions panel
 * @method
 * @namespace Mapifies
 * @id Mapifies.SearchDirections
 * @param {jQuery} element The jQuery object containing the map element.
 * @param {Object} options An object of options
 * @param {Function} callback The callback function that returns the result
 * @return {Function} Returns a passed callback function or true if no callback specified
 */
Mapifies.SearchDirections = function( element, options, callback) {
	/**
	 * Default options for SearchDirections
	 * @method
	 * @namespace Mapifies.SearchDirections
	 * @id Mapifies.SearchDirections.defaults
	 * @alias Mapifies.SearchDirections.defaults
	 * @param {String} query The directions query to parse.  Must contain one 'from:' and one 'to:' query, but can contain multiple 'to:' queries.
	 * @param {String} panel The ID of the panel that the directions will be sent to.
	 * @param {String} local The local for the directions.
	 * @param {String} travelMode Allows you to specify the travel mode, either 'driving' or 'walking'.  Driving is the default.
	 * @param {Boolean} avoidHighways Allows you to avoid Highways/Motorway's on trips.  Please note this may not always be possible depending on the route.
	 * @param {Boolean} getPolyline Decides if the returned result will draw a polyline on the map on the journey.  Default is True.
	 * @param {Boolean} getSteps Decides if the textual directions are returned to the directions panel.
	 * @param {Boolean} preserveViewport Decides if the map will zoom and center in on the directions results.
	 * @param {Boolean} clearLastSearch Clears the last direction search if you do not want to have multiple points.
	 * @return {Object} The options for SearchDirections
	 */
	function defaults() {
		return {
			// From address
			'query': null,
			// Optional panel to show text directions
			'panel': null,
			//The locale to use for the directions result.
			'locale': 'en_GB',
			//The mode of travel, such as driving (default) or walking
			'travelMode': 'driving',
			// Option to avoid highways
			'avoidHighways': false,
			// Get polyline
			'getPolyline': true,
			// Get directions
			'getSteps': true,
			// Preserve Viewport
			'preserveViewport' : false,
			// clear last search
			'clearLastSearch' : false
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	
	var queryOptions = {
		'locale': options.locale,
		'travelMode': options.travelMode,
		'avoidHighways': options.avoidHighways,
		'getPolyline': options.getPolyline,
		'getSteps': options.getSteps,
		'preserveViewport' : options.preserveViewport
	};
	
	var panel = $(options.panel).get(0);
	
	if (typeof thisMap.Directions === 'undefined') {
  	Mapifies.MapObjects.Append(element, 'Directions', new GDirections(thisMap, panel));
  }	
	
	GEvent.addListener(thisMap.Directions, "load", onLoad);
  GEvent.addListener(thisMap.Directions, "error", onError);
	
	if (options.clearLastSearch) {
		thisMap.Directions.clear();
	}
	
	thisMap.Directions.load(options.query, queryOptions);
	
	function onLoad() {
		if (typeof callback == 'function') return callback(thisMap.Directions, options);	
	}
	
	function onError() {
		if (typeof callback == 'function') return callback(thisMap.Directions, options);	
	}
	
	return;
};

/**
 * Create an adsense ads manager for the map.  The Adsense manager will parse your page and show adverts on the map that relate to this.  Requires your adsense publisher id and channel
 * @method
 * @namespace Mapifies
 * @id Mapifies.CreateAdsManager
 * @param {jQuery} element The jQuery object containing the map element.
 * @param {Object} options An object of options
 * @param {Function} callback The callback function that returns the result
 * @return {Function} Returns a passed callback function or true if no callback specified
 */

Mapifies.CreateAdsManager = function( element, options, callback) {
	/**
	 * Default options for CreateAdsManager
	 * @method
	 * @namespace Mapifies.CreateAdsManager
	 * @id Mapifies.CreateAdsManager.defaults
	 * @alias Mapifies.CreateAdsManager.defaults
	 * @param {String} publisherId Your Adsense publisher ID
	 * @param {Number} maxAdsOnMap The maximum number of ads to show on the map at one time
	 * @param {Number} channel The AdSense channel this belongs to
	 * @param {Number} minZoomLevel The minimum zoom level to begin showing ads at
	 * @return {Object} The options for CreateAdsManager
	 */
	function defaults() {
		return {
			'publisherId':'',
			'maxAdsOnMap':3,
			'channel':0,
			'minZoomLevel':6
		}
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	
	var adsOptions = {
		'maxAdsOnMap':options.maxAdsOnMap,
		'channel':options.channel,
		'minZoomLevel':options.minZoomLevel
	}
	
	if (typeof thisMap.AdsManager == 'undefined') {
  	Mapifies.MapObjects.Append(element, 'AdsManager', new GAdsManager(thisMap, options.publisherId, adsOptions));
  }	
	
	if (typeof callback == 'function') return callback(thisMap.AdsManager, options);
};
/**
 * This function allows you to pass a GeoXML or KML feed to a Google map.
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddFeed
 * @alias Mapifies.AddFeed
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Fucntion} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the feed object and options.
 */
Mapifies.AddFeed = function( element, options, callback ) {
	/**
	 * Default options for AddFeed
	 * @method
	 * @namespace Mapifies.AddFeed
	 * @id Mapifies.AddFeed.defaults
	 * @alias Mapifies.AddFeed.defaults
	 * @param {String} feedUrl The URL of the GeoXML or KML feed.
	 * @param {Object} mapCenter An array with a lat/lng position to center the map on
	 * @return {Object} The options for AddFeed
	 */
	function defaults() {
		return {
			// URL of the feed to pass (required)
			'feedUrl': null,
			// Position to center the map on (optional)
			'mapCenter': []
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);

	// Load feed
	var feed = new GGeoXml(options.feedUrl);
	// Add as overlay
	thisMap.addOverlay(feed);
	
	// If the user has passed the optional mapCenter,
	// then center the map on that point
	if (options.mapCenter[0] && options.mapCenter[1])
		thisMap.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]));
		
	if (typeof callback == 'function') return callback( feed, options );
	return;
};

/**
 * This function allows you to remove a GeoXML or KML feed from a Google map.
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveFeed
 * @alias Mapifies.RemoveFeed
 * @param {jQuery} element The element to initialise the map on.
 * @param {GGeoXML} feed The feed to remove from the map
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the feed object and options.
 */
Mapifies.RemoveFeed = function ( element, feed, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(feed);
	if (typeof callback == 'function') return callback( feed );
	return;
};
/**
 * This function allows you to add a ground overlay to a map
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddGroundOverlay
 * @alias Mapifies.AddGroundOverlay
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the feed object and options.
 */
Mapifies.AddGroundOverlay = function( element, options, callback) {
  /**
	 * Default options for AddGroundOverlay
	 * @method
	 * @namespace Mapifies.AddGroundOverlay
	 * @id Mapifies.AddGroundOverlay.defaults
	 * @alias Mapifies.AddGroundOverlay.defaults
	 * @param {Object} overlaySouthWestBounds The coordinates of the South West bounds of the image
	 * @param {Object} overlayNorthEastBounds The coordinates of the North East bounds of the image
	 * @param {String} overlayImage The URL of the image to be loaded
	 * @return {Object} The options for AddGroundOverlay
	 */
	function defaults() {
		return {
			// South West Boundry
			'overlaySouthWestBounds': undefined,
			// North East Boundry
			'overlayNorthEastBounds': undefined,
			// Image
			'overlayImage': undefined
		};
	};
	
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	
	var boundries = new GLatLngBounds(new GLatLng(options.overlaySouthWestBounds[0], options.overlaySouthWestBounds[1]), new GLatLng(options.overlayNorthEastBounds[0], options.overlayNorthEastBounds[1]));
	groundOverlay = new GGroundOverlay(options.overlayImage, boundries);
	
	thisMap.addOverlay(groundOverlay);
		
	if (typeof callback == 'function') return callback( groundOverlay, options );
	return;
};

/**
 * This function removes an existing ground overlay
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveGroundOverlay
 * @alias Mapifies.RemoveGroundOverlay
 * @param {jQuery} element The element to initialise the map on.
 * @param {GGroundOverlay} groundOverlay The ground overlay to remove.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the feed object and options.
 */
Mapifies.RemoveGroundOverlay = function ( element, groundOverlay, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(groundOverlay);
	if (typeof callback === 'function') return callback(groundOverlay);
	return;
};
/**
 * This function allows you to add markers to the map with several options
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddMarker
 * @alias Mapifies.AddMarker
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the marker object and options.
 */
Mapifies.AddMarker = function ( element, options, callback ) {
	/**
	 * Default options for AddGroundOverlay
	 * @method
	 * @namespace Mapifies.AddGroundOverlay
	 * @id Mapifies.AddGroundOverlay.defaults
	 * @alias Mapifies.AddGroundOverlay.defaults
	 * @param {Object} pointLatLng The Lat/Lng coordinates of the marker.
	 * @param {String} pointHTML The HTML to appear in the markers info window.
	 * @param {String} pointOpenHTMLEvent The javascript event type to open the marker info window.  Default is 'click'.
	 * @param {Boolean} pointIsDraggable Defines if the point is draggable by the end user.  Default false.
	 * @param {Boolean} pointIsRemovable Defines if the point can be removed by the user.  Default false.
	 * @param {Boolean} pointRemoveEvent The event type to remove a marker.  Default 'dblclick'.
	 * @param {Number} pointMinZoom The minimum zoom level to display the marker if using a marker manager.
	 * @param {Number} pointMaxZoom The maximum zoom level to display the marker if using a marker manager.
	 * @param {GIcon} pointIcon A GIcon to display instead of the standard marker graphic.
	 * @param {Boolean} centerMap Automatically center the map on the new marker.  Default false.
	 * @param {String} centerMoveMethod The method in which to move to the marker.  Options are 'normal' (default) and 'pan'.  Added r64
	 * @return {Object} The options for AddGroundOverlay
	 */
	function defaults() {
		var values = {
			'pointLatLng': undefined,
			'pointHTML': undefined,
			'pointOpenHTMLEvent': 'click',
			'pointIsDraggable': false,
			'pointIsRemovable': false,
			'pointRemoveEvent': 'dblclick',
			'pointMinZoom': 4,
			'pointMaxZoom': 17,
			'pointIcon': 'mapka_ikonka_0.png',
			'centerMap': true,
			'centerMoveMethod':'normal'
		};
		return values;
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend({}, defaults(), options);
	
	var markerOptions = {}
	
	if (options.pointIcon.length){
      var Icon = new GIcon();
      Icon.image = 'layout/graphic/'+options.pointIcon;
      Icon.iconSize = new GSize(19, 35);
      Icon.shadow = 'layout/graphic/mapka_ikonka_cien.png';
      Icon.shadowSize = new GSize(40, 35);
      Icon.iconAnchor = new GPoint(5, 34);
      Icon.infoWindowAnchor = new GPoint(5, 2);
      Icon.transparent = "layout/graphic/"+options.pointIcon;
      Icon.printImage = "layout/graphic/"+options.pointIcon;
      Icon.mozPrintImage = "layout/graphic/"+options.pointIcon;
      Icon.printShadow = "layout/graphic/mapka_ikonka_cien.png";
      Icon.imageMap=[9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,
       19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,
       16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0];

		
		jQuery.extend(markerOptions, {'icon':  Icon });
	}	
	if (options.pointIsDraggable)
		jQuery.extend(markerOptions, {'draggable': options.pointIsDraggable});
			
	if (options.centerMap) {
		switch (options.centerMoveMethod) {
			case 'normal':
				thisMap.setCenter(new GLatLng(options.pointLatLng[0],options.pointLatLng[1]));
			break;
			case 'pan':
				thisMap.panTo(new GLatLng(options.pointLatLng[0],options.pointLatLng[1]));
			break;
		}
	}
		
		
	// Create marker, optional parameter to make it draggable
	var marker = new GMarker(new GLatLng(options.pointLatLng[0],options.pointLatLng[1]), markerOptions);
		
	// If it has HTML to pass in, add an event listner for a click
	if(options.pointHTML)
		GEvent.addListener(marker, options.pointOpenHTMLEvent, function(){
			marker.openInfoWindowHtml(options.pointHTML, {maxContent: options.pointMaxContent, maxTitle: options.pointMaxTitle});
		});
	// If it is removable, add dblclick event
	if(options.pointIsRemovable)
		GEvent.addListener(marker, options.pointRemoveEvent, function(){
			thisMap.removeOverlay(marker);
		});

	// If the marker manager exists, add it
	if(thisMap.MarkerManager) {
		thisMap.MarkerManager.addMarker(marker, options.pointMinZoom, options.pointMaxZoom);	
	} else {
		// Direct rendering to map
		thisMap.addOverlay(marker);
	}
		
	if (typeof callback == 'function') return callback(marker, options);
	return;
};


/**
 * This function allows you to remove markers from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveMarker
 * @alias Mapifies.RemoveMarker
 * @param {jQuery} element The element to initialise the map on.
 * @param {GMarker} options The marker to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the marker object.
 */
Mapifies.RemoveMarker = function ( element, marker, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(marker);
	if (typeof callback === 'function') return callback(marker);
	return;
};

/**
 * This function allows you to create a marker manager to store and manage any markers created on the map.  Google recommends not using this marker manager and instead using the open source one.
 * @method
 * @deprecated
 * @namespace Mapifies
 * @id Mapifies.CreateMarkerManager
 * @alias Mapifies.CreateMarkerManager
 * @param {jQuery} element The element to initialise the map on.
 * @param {GMarker} options The marker to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the marker object and options.
 */
Mapifies.CreateMarkerManager = function(element, options, callback) {
	/**
	 * Default options for CreateMarkerManager
	 * @method
	 * @namespace Mapifies.CreateMarkerManager
	 * @id Mapifies.CreateMarkerManager.defaults
	 * @alias Mapifies.CreateMarkerManager.defaults
	 * @param {String} markerManager The type of marker manager to use.  Options are 'GMarkerManager' (default) and 'MarkerManager'.  (Added r72)
	 * @param {Number} borderPadding Specifies, in pixels, the extra padding outside the map's current viewport monitored by a manager. Markers that fall within this padding are added to the map, even if they are not fully visible.
	 * @param {Number} maxZoom The maximum zoom level to show markers at
	 * @param {Boolean} trackMarkers Indicates whether or not a marker manager should track markers' movements.
	 * @return {Object} The options for CreateMarkerManager
	 */
	function defaults() {
		return {
			'markerManager': 'GMarkerManager',
			// Border Padding in pixels
			'borderPadding': 100,
			// Max zoom level 
			'maxZoom': 17,
			// Track markers
			'trackMarkers': false
		}
	}
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	
	var markerManagerOptions = {
		'borderPadding': options.borderPadding,
		'maxZoom': options.maxZoom,
		'trackMarkers': options.trackMarkers
	}
	
	var markerManager = new window[options.markerManager](thisMap, options);
	Mapifies.MapObjects.Append(element, 'MarkerManager',markerManager);

	// Return the callback
	if (typeof callback == 'function') return callback( markerManager, options );
};
/**
 * This function allows you to add a polygon to a map using GLatLng points
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddPolygon
 * @alias Mapifies.AddPolygon
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the polygon object, polygon options and options.
 */
Mapifies.AddPolygon = function( element, options, callback ) {
	/**
	 * Default options for AddPolygon
	 * @method
	 * @namespace Mapifies.AddPolygon
	 * @id Mapifies.AddPolygon.defaults
	 * @alias Mapifies.AddPolygon.defaults
	 * @param {Object} polygonPoints An array of Lat/Lng points that make up the vertexes of the polygon.
	 * @param {String} polygonStrokeColor The stroke colour for the polygon.
	 * @param {Number} polygonStrokeWeight The thickness of the polygon line.
	 * @param {Number} polygonStrokeOpacity A value from 0 to 1 of for the line opacity.
	 * @param {String} polygonFillColor The colour of the fill area for the polygon.
	 * @param {Number} polygonFillOpacity The value from 0 to 1 for the polygon fill opacity.
	 * @param {Object} mapCenter An array containing the LatLng point to center on.
	 * @param {Boolean} polygonClickable Defines if the polygon is clickable or not. Default true.
	 * @return {Object} The options for AddPolygon
	 */
	function defaults() {
		return {
			// An array of GLatLng objects
			'polygonPoints': [],
			// The outer stroke colour
	 		'polygonStrokeColor': "#000000",
	 		// Stroke thickness
	 		'polygonStrokeWeight': 5,
	 		// Stroke Opacity
	 		'polygonStrokeOpacity': 1,
	 		// Fill colour
	 		'polygonFillColor': "#ff0000",
	 		// Fill opacity
	 		'polygonFillOpacity': 1,
	 		// Optional center map
	 		'mapCenter': undefined,
	 		// Is polygon clickable?
	 		'polygonClickable': true
		}
	}
	
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	var polygonOptions = {};
	
	if (!options.polygonClickable)
		polygonOptions = jQuery.extend(polygonOptions, {clickable: false});
	 		
	if(typeof options.mapCenter !== 'undefined' && options.mapCenter[0] && options.mapCenter[1])
		thisMap.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]));
	
	var allPoints = [];
	jQuery.each(options.polygonPoints, function(i, point) {
		allPoints.push(new GLatLng(point[0],point[1]));
	});
	
	var polygon = new GPolygon(allPoints, options.polygonStrokeColor, options.polygonStrokeWeight, options.polygonStrokeOpacity, options.polygonFillColor, options.polygonFillOpacity, polygonOptions);
	thisMap.addOverlay(polygon);
		
	if (typeof callback == 'function') return callback(polygon, polygonOptions, options);
	return;
}

/**
 * This function allows you to remove a polygon from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemovePolygon
 * @alias Mapifies.RemovePolygon
 * @param {jQuery} element The element to initialise the map on.
 * @param {GPolygon} polygon The polygon to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the polygon.
 */
Mapifies.RemovePolygon = function ( element, polygon, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(polygon);
	if (typeof callback === 'function') return callback(polygon);
	return;
};
/**
 * This function allows you to add a polyline to a map using GLatLng points
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddPolyline
 * @alias Mapifies.AddPolyline
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the polygon object, polygon options and options.
 */
Mapifies.AddPolyline = function (element, options, callback) {
	/**
	 * Default options for AddPolyline
	 * @method
	 * @namespace Mapifies.AddPolyline
	 * @id Mapifies.AddPolygon.defaults
	 * @alias Mapifies.AddPolygon.defaults
	 * @param {Object} polylinePoints An array of Lat/Lng points that make up the vertexes of the polyline.
	 * @param {String} polylineStrokeColor The stroke colour for the polyline.
	 * @param {Number} polylineStrokeWidth The thickness of the polyline line.
	 * @param {Number} polylineStrokeOpacity A value from 0 to 1 of for the line opacity.
	 * @param {Object} mapCenter An array containing the LatLng point to center on.
	 * @param {Boolean} polylineGeodesic Defines if the line follows the curve of the earth.  Default false.
	 * @param {Boolean} polylineClickable Defines if the polygon is clickable or not. Default true.
	 * @return {Object} The options for AddPolyline
	 */
	function defaults() {
		return {
			// An array of GLatLng objects
			'polylinePoints': [],
			// Colour of the line
			'polylineStrokeColor': "#ff0000",
			// Width of the line
			'polylineStrokeWidth': 10,
			// Opacity of the line
			'polylineStrokeOpacity': 1,
			// Optional center map
			'mapCenter': [],
			// Is line Geodesic (i.e. bends to the curve of the earth)?
			'polylineGeodesic': false,
			// Is line clickable?
			'polylineClickable': true
		};
	};
	
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	var polyLineOptions = {};
	if (options.polylineGeodesic)
		jQuery.extend(polyLineOptions, {geodesic: true});
			
	if(!options.polylineClickable)
		jQuery.extend(polyLineOptions, {clickable: false});

	if (options.mapCenter[0] && options.mapCenter[1])
		thisMap.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]));

	var allPoints = [];
	jQuery.each(options.polylinePoints, function(i, point) {
		allPoints.push(new GLatLng(point[0],point[1]));
	});

	var polyline = new GPolyline(allPoints, options.polylineStrokeColor, options.polylineStrokeWidth, options.polylineStrokeOpacity, polyLineOptions);
	thisMap.addOverlay(polyline);
		
	if (typeof callback == 'function') return callback(polyline, polyLineOptions, options);
	return;
}

/**
 * This function allows you to remove a polyline from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemovePolyline
 * @alias Mapifies.RemovePolyline
 * @param {jQuery} element The element to initialise the map on.
 * @param {GPolyline} polyline The polyline to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the polyline.
 */
Mapifies.RemovePolyline = function (element, polyline, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(polyline);
	if (typeof callback === 'function') return callback(polyline);
	return;
};

/**
 * This function allows you to add a screen overlay to a map.
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddScreenOverlay
 * @alias Mapifies.AddScreenOverlay
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the screen overlay and options.
 */
Mapifies.AddScreenOverlay = function( element, options, callback ) {
	/**
	 * Default options for AddScreenOverlay
	 * @method
	 * @namespace Mapifies.AddScreenOverlay
	 * @id Mapifies.AddScreenOverlay.defaults
	 * @alias Mapifies.AddScreenOverlay.defaults
	 * @param {String} imageUrl The URL of the image to load.
	 * @param {Object} screenXY The X/Y position in the viewport to place the image.
	 * @param {Object} overlayXY The overlay X/Y position in the viewport.
	 * @param {Object} size The size of the image, which is converted to a GSize.
	 * @return {Object} The options for AddScreenOverlay
	 */
	function defaults() {
		return {
			'imageUrl':'',
			'screenXY':[],
			'overlayXY':[],
			'size':[]
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);

	var overlay = new GScreenOverlay(options.imageUrl, new GScreenPoint(options.screenXY[0],options.screenXY[1]), new GScreenPoint(options.overlayXY[0],options.overlayXY[1]), new GScreenSize(options.size[0],options.size[1]));
	thisMap.addOverlay(overlay);
		
	if (typeof callback == 'function') return callback(overlay, options);
};

/**
 * This function allows you to remove a screen overlay from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveScreenOverlay
 * @alias Mapifies.RemoveScreenOverlay
 * @param {jQuery} element The element to initialise the map on.
 * @param {GScreenOverlay} overlay The overlay to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the overlay.
 */
Mapifies.RemoveScreenOverlay = function ( element, overlay, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(overlay);
	if (typeof callback === 'function') return callback(overlay);
	return;
};

/**
 * This function allows you to add a Google Streetview
 * @method
 * @namespace Mapifies
 * @id Mapifies.CreateStreetviewPanorama
 * @alias Mapifies.CreateStreetviewPanorama
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the street view.
 */
Mapifies.CreateStreetviewPanorama = function( element, options, callback ) {
	/**
	 * Default options for CreateStreetviewPanorama
	 * @method
	 * @namespace Mapifies.CreateStreetviewPanorama
	 * @id Mapifies.CreateStreetviewPanorama.defaults
	 * @alias Mapifies.CreateStreetviewPanorama.defaults
	 * @param {String} overideContainer A ID of a div to put the street view into, otherwise it will default to the map.
	 * @param {Object} latlng The starting Lat/Lng of the streetview - this is required.
	 * @param {Object} pov The point of view to initialse the map on.  This is 3 values, X/Y/Z
	 * @return {Object} The options for CreateStreetviewPanorama
	 */
	function defaults() {
		return {
			'overideContainer':'',
			'latlng':[40.75271883902363, -73.98262023925781],
			'pov': []
		}
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);
	// Create Street View Overlay
	
	var container = null;
	if (options.overideContainer !== '') {
		container = jQuery(options.overideContainer).get(0);
	} else {
		container = jQuery(element).get(0);
	}
	
	var viewOptions = {};
	if (options.pov.length > 0) {
		jQuery.extend(viewOptions, {'pov':new GPov(options.latlng[0],options.latlng[1],options.latlng[2])});
	}
	if (options.latlng.length > 0) {
		jQuery.extend(viewOptions, {'latlng':new GLatLng(options.latlng[0],options.latlng[1])});
	}
	
	var overlay = new GStreetviewPanorama(container, viewOptions);
	if (typeof callback == 'function') return callback(overlay, options);
	return;
};

/**
 * This function allows you to remove a street view from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveStreetviewPanorama
 * @alias Mapifies.RemoveStreetviewPanorama
 * @param {jQuery} element The element to initialise the map on.
 * @param {GStreetView} view The view to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the view.
 */
Mapifies.RemoveStreetviewPanorama = function ( element, view, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	view.remove();
	if (typeof callback == 'function') return callback( view );
	return;
};
/**
 * This function allows you to add a Google Traffic Layer
 * @method
 * @namespace Mapifies
 * @id Mapifies.AddTrafficInfo
 * @alias Mapifies.AddTrafficInfo
 * @param {jQuery} element The element to initialise the map on.
 * @param {Object} options The object that contains the options.
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the traffic layer.
 */
Mapifies.AddTrafficInfo = function( element, options, callback) {
	/**
	 * Default options for AddTrafficInfo
	 * @method
	 * @namespace Mapifies.AddTrafficInfo
	 * @id Mapifies.AddTrafficInfo.defaults
	 * @alias Mapifies.AddTrafficInfo.defaults
	 * @param {Object} mapCenter The Lat/Lng to center the map on
	 * @return {Object} The options for AddTrafficInfo
	 */
	function defaults() {
		return {
			// Center the map on this point (optional)
			'mapCenter': []
		};
	};
	var thisMap = Mapifies.MapObjects.Get(element);
	options = jQuery.extend(defaults(), options);

	var trafficOverlay = new GTrafficOverlay;
	// Add overlay
	thisMap.addOverlay(trafficOverlay);
	// If the user has passed the optional mapCenter,
	// then center the map on that point
	if (options.mapCenter[0] && options.mapCenter[1]) {
		thisMap.setCenter(new GLatLng(options.mapCenter[0], options.mapCenter[1]));
	}
	if (typeof callback == 'function') return callback(trafficOverlay, options);
};

/**
 * This function allows you to remove a traffic layer from the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.RemoveTrafficInfo
 * @alias Mapifies.RemoveTrafficInfo
 * @param {jQuery} element The element to initialise the map on.
 * @param {GTrafficOverlay} trafficOverlay The traffic overlay to be removed
 * @param {Function} callback The callback function to pass out after initialising the map.
 * @return {Function} callback The callback option with the traffic overlay.
 */
Mapifies.RemoveTrafficInfo = function ( element, trafficOverlay, callback ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	thisMap.removeOverlay(trafficOverlay);
	if (typeof callback === 'function') return callback(trafficOverlay);
	return;
};
/**
 * A helper method that allows you to pass the status code of a search and get back a friendly oject
 * @method
 * @namespace Mapifies
 * @id Mapifies.SearchCode
 * @param {Number} code The status code of the query
 * @return {Object} Returns a friendly object that contains the 'code', a 'success' boolean and a helpful 'message'.
 */
Mapifies.SearchCode = function ( code ) {
	switch (code) {
		case G_GEO_SUCCESS:
			return {'code':G_GEO_SUCCESS,'success':true,'message':'Success'};
		case G_GEO_UNKNOWN_ADDRESS:
			return {'code' : G_GEO_UNKNOWN_ADDRESS, 'success' : false, 'message' : 'No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect'};
			break;
		case G_GEO_SERVER_ERROR:
			return {'code' : G_GEO_UNKNOWN_ADDRESS, 'success' : false, 'message' : 'A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.'};
			break;
		case G_GEO_MISSING_QUERY:
			return {'code' : G_GEO_UNKNOWN_ADDRESS, 'success' : false, 'message' : 'The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.'};
			break;
		case G_GEO_BAD_KEY:
			return {'code' : G_GEO_UNKNOWN_ADDRESS, 'success' : false, 'message' : 'The given key is either invalid or does not match the domain for which it was given.'};
			break;
		case G_GEO_BAD_REQUEST:
			return {'code' : G_GEO_UNKNOWN_ADDRESS, 'success' : false, 'message' : 'A directions request could not be successfully parsed.'};
			break;
		default:
			return {
				'code': null,
				'success': false,
				'message': 'An unknown error occurred.'
			};
		break;
	};
}

/**
 * An internal function to get the google maptype constant
 * @method
 * @namespace Mapifies
 * @id Mapifies.GetMapType
 * @alias Mapifies.GetMapType
 * @param {String} mapType The string of the map type.
 * @return {String} mapType The Google constant for a maptype.
 */
Mapifies.GetMapType = function ( mapType ) {
	// Lets set our map type based on the options
	switch(mapType) {
		case 'map':	// Normal Map
			mapType = G_NORMAL_MAP;
		break;
		case 'sat':	// Satallite Imagery
			mapType = G_SATELLITE_MAP;
		break;
		case 'hybrid':	//Hybrid Map
			mapType = G_HYBRID_MAP;
		break;
	};
	return mapType;
};

/**
 * An internal function to get the google travel mode constant
 * @method
 * @namespace Mapifies
 * @id Mapifies.GetTravelMode
 * @alias Mapifies.GetTravelMode
 * @param {String} travelMode The string of the travel mode.
 * @return {String} travelMode The Google constant for a travel mode.
 */
Mapifies.GetTravelMode = function ( travelMode ) {
	switch(travelMode) {
		case 'driving':	
			travelMode = G_TRAVEL_MODE_DRIVING;
		break;
		case 'walking':	
			travelMode = G_TRAVEL_MODE_WALKING;
		break;
	};
	return travelMode;
};

/**
 * A helper function to create a google GIcon
 * @method
 * @namespace Mapifies
 * @id Mapifies.createIcon
 * @alias Mapifies.createIcon
 * @param {Object} options The options to create the icon
 * @return {GIcon} A GIcon object
 */
Mapifies.createIcon = function (options) {
	/**
	 * Default options for createIcon
	 * @method
	 * @namespace Mapifies.createIcon
	 * @id Mapifies.createIcon.defaults
	 * @alias Mapifies.createIcon.defaults
	 * @param {String} iconImage The foreground image URL of the icon.
	 * @param {String} iconShadow The shadow image URL of the icon.
	 * @param {GSize} iconSize The pixel size of the foreground image of the icon.
	 * @param {GSize} iconShadowSize The pixel size of the shadow image.
	 * @param {GPoint} iconAnchor The pixel coordinate relative to the top left corner of the icon image at which this icon is anchored to the map.
	 * @param {GPoint} iconInfoWindowAnchor The pixel coordinate relative to the top left corner of the icon image at which the info window is anchored to this icon.
	 * @param {String} iconPrintImage The URL of the foreground icon image used for printed maps. It must be the same size as the main icon image given by image.
	 * @param {String} iconMozPrintImage The URL of the foreground icon image used for printed maps in Firefox/Mozilla. It must be the same size as the main icon image given by image.
	 * @param {String} iconPrintShadow The URL of the shadow image used for printed maps. It should be a GIF image since most browsers cannot print PNG images.
	 * @param {String} iconTransparent The URL of a virtually transparent version of the foreground icon image used to capture click events in Internet Explorer. This image should be a 24-bit PNG version of the main icon image with 1% opacity, but the same shape and size as the main icon.
	 * @return {Object} The options for createIcon
	 */
	function defaults() {
		return {
			'iconImage': undefined,
			'iconShadow': undefined,
			'iconSize': undefined,
			'iconShadowSize': undefined,
			'iconAnchor': undefined,
			'iconInfoWindowAnchor': undefined,
			'iconPrintImage': undefined,
			'iconMozPrintImage': undefined,
			'iconPrintShadow': undefined,
			'iconTransparent': undefined
		};
	};
	
	options = jQuery.extend(defaults(), options);
	var icon = new GIcon(G_DEFAULT_ICON);
		
	if(options.iconImage)
		icon.image = options.iconImage;
	if(options.iconShadow)
		icon.shadow = options.iconShadow;
	if(options.iconSize)
		icon.iconSize = options.iconSize;
	if(options.iconShadowSize)
		icon.shadowSize = options.iconShadowSize;
	if(options.iconAnchor)
		icon.iconAnchor = options.iconAnchor;
	if(options.iconInfoWindowAnchor)
		icon.infoWindowAnchor = options.iconInfoWindowAnchor;
	return icon;
};

/**
 * A helper function to get the map center as a GLatLng
 * @method
 * @namespace Mapifies
 * @id Mapifies.getCenter
 * @alias Mapifies.getCenter
 * @param {jQuery} element The element that contains the map.
 * @return {GLatLng} A object containing the center of the map
 */
Mapifies.getCenter = function ( element ) {
	var thisMap = Mapifies.MapObjects.Get(element);
	return thisMap.getCenter();
};

/**
 * A helper function to get the bounds of the map
 * @method
 * @namespace Mapifies
 * @id Mapifies.getBounds
 * @alias Mapifies.getBounds
 * @param {jQuery} element The element that contains the map.
 * @return {GSize} The bounds of the map
 */
Mapifies.getBounds = function (element){
	var thisMap = Mapifies.MapObjects.Get(element);
	return thisMap.getBounds();
};var Mapifies;

if (!Mapifies) Mapifies = {};

(function($){
	$.fn.jmap = function(method, options, callback) {
		return this.each(function(){
			if (method == 'init' && typeof options == 'undefined') {
				new Mapifies.Initialise(this, {}, null);
			} else if (method == 'init' && typeof options == 'object') {
				new Mapifies.Initialise(this, options, callback);
			} else if (method == 'init' && typeof options == 'function') {
				new Mapifies.Initialise(this, {}, options);
			} else if (typeof method == 'object' || method == null) {
				new Mapifies.Initialise(this, method, options);
			} else {
				try {
					new Mapifies[method](this, options, callback);
				} catch(err) {
					throw Error('Mapifies Function Does Not Exist');
				}
			}
		});
	}
})(jQuery);

/**
 * 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-Plugin "preloadCssImages"
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/
 * demo page: http://www.filamentgroup.com/examples/preloadImages/index_v2.php
 * 
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Version: 5.0, 10.31.2008
 * Changelog:
 * 	02.20.2008 initial Version 1.0
 *    06.04.2008 Version 2.0 : removed need for any passed arguments. Images load from any and all directories.
 *    06.21.2008 Version 3.0 : Added options for loading status. Fixed IE abs image path bug (thanks Sam Pohlenz).
 *    07.24.2008 Version 4.0 : Added support for @imported CSS (credit: http://marcarea.com/). Fixed support in Opera as well. 
 *    10.31.2008 Version: 5.0 : Many feature and performance enhancements from trixta
 * --------------------------------------------------------------------
 */

;jQuery.preloadCssImages = function(settings){
	settings = jQuery.extend({
		statusTextEl: null,
		statusBarEl: null,
		errorDelay: 999, // handles 404-Errors in IE
		simultaneousCacheLoading: 2
	}, settings);
	var allImgs = [],
		loaded = 0,
		imgUrls = [],
		thisSheetRules,	
		errorTimer;
	
	function onImgComplete(){
		clearTimeout(errorTimer);
		if (imgUrls && imgUrls.length && imgUrls[loaded]) {
			loaded++;
			if (settings.statusTextEl) {
				var nowloading = (imgUrls[loaded]) ? 
					'Now Loading: <span>' + imgUrls[loaded].split('/')[imgUrls[loaded].split('/').length - 1] : 
					'Loading complete'; // wrong status-text bug fixed
				jQuery(settings.statusTextEl).html('<span class="numLoaded">' + loaded + '</span> of <span class="numTotal">' + imgUrls.length + '</span> loaded (<span class="percentLoaded">' + (loaded / imgUrls.length * 100).toFixed(0) + '%</span>) <span class="currentImg">' + nowloading + '</span></span>');
			}
			if (settings.statusBarEl) {
				var barWidth = jQuery(settings.statusBarEl).width();
				jQuery(settings.statusBarEl).css('background-position', -(barWidth - (barWidth * loaded / imgUrls.length).toFixed(0)) + 'px 50%');
			}
			loadImgs();
		}
	}
	
	function loadImgs(){
		//only load 1 image at the same time / most browsers can only handle 2 http requests, 1 should remain for user-interaction (Ajax, other images, normal page requests...)
		// otherwise set simultaneousCacheLoading to a higher number for simultaneous downloads
		if(imgUrls && imgUrls.length && imgUrls[loaded]){
			var img = new Image(); //new img obj
			img.src = imgUrls[loaded];	//set src either absolute or rel to css dir
			if(!img.complete){
				jQuery(img).bind('error load onreadystatechange', onImgComplete);
			} else {
				onImgComplete();
			}
			errorTimer = setTimeout(onImgComplete, settings.errorDelay); // handles 404-Errors in IE
		}
	}
	
	function parseCSS(sheets, urls) {
		var w3cImport = false,
			imported = [],
			importedSrc = [],
			baseURL;
		var sheetIndex = sheets.length;
		while(sheetIndex--){//loop through each stylesheet
			
			var cssPile = '';//create large string of all css rules in sheet
			
			if(urls && urls[sheetIndex]){
				baseURL = urls[sheetIndex];
			} else {
				var csshref = (sheets[sheetIndex].href) ? sheets[sheetIndex].href : 'window.location.href';
				var baseURLarr = csshref.split('/');//split href at / to make array
				baseURLarr.pop();//remove file path from baseURL array
				baseURL = baseURLarr.join('/');//create base url for the images in this sheet (css file's dir)
				if (baseURL) {
					baseURL += '/'; //tack on a / if needed
				}
			}
			if(sheets[sheetIndex].cssRules || sheets[sheetIndex].rules){
				thisSheetRules = (sheets[sheetIndex].cssRules) ? //->>> http://www.quirksmode.org/dom/w3c_css.html
					sheets[sheetIndex].cssRules : //w3
					sheets[sheetIndex].rules; //ie 
				var ruleIndex = thisSheetRules.length;
				while(ruleIndex--){
					if(thisSheetRules[ruleIndex].style && thisSheetRules[ruleIndex].style.cssText){
						var text = thisSheetRules[ruleIndex].style.cssText;
						if(text.toLowerCase().indexOf('url') != -1){ // only add rules to the string if you can assume, to find an image, speed improvement
							cssPile += text; // thisSheetRules[ruleIndex].style.cssText instead of thisSheetRules[ruleIndex].cssText is a huge speed improvement
						}
					} else if(thisSheetRules[ruleIndex].styleSheet) {
						imported.push(thisSheetRules[ruleIndex].styleSheet);
						w3cImport = true;
					}
					
				}
			}
			//parse cssPile for image urls
			var tmpImage = cssPile.match(/[^\("]+\.(gif|jpg|jpeg|png)/g);//reg ex to get a string of between a "(" and a ".filename" / '"' for opera-bugfix
			if(tmpImage){
				var i = tmpImage.length;
				while(i--){ // handle baseUrl here for multiple stylesheets in different folders bug
					var imgSrc = (tmpImage[i].charAt(0) == '/' || tmpImage[i].match('://')) ? // protocol-bug fixed
						tmpImage[i] : 
						baseURL + tmpImage[i];
					
					if(jQuery.inArray(imgSrc, imgUrls) == -1){
						imgUrls.push(imgSrc);
					}
				}
			}
			
			if(!w3cImport && sheets[sheetIndex].imports && sheets[sheetIndex].imports.length) {
				for(var iImport = 0, importLen = sheets[sheetIndex].imports.length; iImport < importLen; iImport++){
					var iHref = sheets[sheetIndex].imports[iImport].href;
					iHref = iHref.split('/');
					iHref.pop();
					iHref = iHref.join('/');
					if (iHref) {
						iHref += '/'; //tack on a / if needed
					}
					var iSrc = (iHref.charAt(0) == '/' || iHref.match('://')) ? // protocol-bug fixed
						iHref : 
						baseURL + iHref;
					
					importedSrc.push(iSrc);
					imported.push(sheets[sheetIndex].imports[iImport]);
				}
				
				
			}
		}//loop
		if(imported.length){
			parseCSS(imported, importedSrc);
			return false;
		}
		var downloads = settings.simultaneousCacheLoading;
		while( downloads--){
			setTimeout(loadImgs, downloads);
		}
	}
	parseCSS(document.styleSheets);
	return imgUrls;
};

