$(document).ready(function(){

	if(ltie7) {
		$('.resultat_thematique h4:first-child, .resultat_mot_cle h4:first-child').css({marginTop: 0});
		$('.resultat_thematique ul + p').css({marginTop: 0});
		$('.resultat_thematique h4 + p, .resultat_thematique h4 + ul, .resultat_thematique p + ul').css({margin: 0});
	}

	pngBgForIe.init();
	lisa.init();
	poll.init();
	nouscontacter.init();
	contactPlus.init();
	liensEvitement.init();

	partager.init();

	ongletsRecherche.init();

	$('#slp_button_div').remove();

	/* hack pour le service conso */
	var disabled = '';
	$('form.questionThematique').submit(function(){
		var select = $(this).find('select').attr('id');
		var option = '#' + select + ' option';
		$(option).each(function() {
			if ($(this).attr('selected')) {
				disabled = 0;
				if ($(this).attr('disabled')) {
					disabled = 1;
				}
			}
		});

		var val=$(this).find('select').val();
		val = val.replace(/ /mg, '_');
		val = val.split(":");
		if (disabled == 1) {
			return false;
		} else {
			if (val[3]) {
				location.href="/Service-Consommateurs/("+val[0]+")/"+val[1]+"/"+val[2]+"/(id)/"+val[3];
			} else {
				location.href="/Service-Consommateurs/("+val[0]+")/"+val[1]+"/(id)/"+val[2];
			}
		}
		return false;
	});

	if ($("#lancement_popup").text() != "0") {
		name = 'enqueteLP=';
		var i = document.cookie.indexOf( name);
		if (i == -1) {
			$('#div_enquete_sc').css({left: '25%'});
			$("#thematique select").hide(); // on cache les select pour ie6
			$('#list_over').hide();
			$('#q_reclamation').hide();
			$('.select').hide();
			$('img[src$=.png]').iunfixpng();
		}
	}

	$('#commencer').click(function() {
		if ($("#lancement_popup").text() != "0") {
			window.open(	'/enquete_sc/repondre?questionnaire=1',
							'popup',
							'scrollbars=no, width=660, height=520, resizable=no, screenX=50, screenY=50'
			);
			$('#div_enquete_sc').css({left: '-9999px'});
			$('#list_over').show();
			$('#q_reclamation').show();
			$('.select').show();
			$("#thematique select").show(); // on reaffiche les select pour ie6
		}
	});

	$('#enquete_sc #fermer').click(function() {
		$('#div_enquete_sc').css({left: '-9999px'});
		$("#thematique select").show(); // on reaffiche les select pour ie6
		$('#list_over').show();
		$('.select').show();
		$('#q_reclamation').show();
		return false;
	});
	$('#navigationConso #menuConso .menuConsoItem .menuConsoLink').each(function() {
		$(this).dblclick(function() {
			document.location = $(this).attr('href');
		});
	});

	$('#slp_retour div').html("Le numéro de suivi est composé de 13 caractères et figure sur la preuve de dépôt.<br/><br/>Numéro de suivi de votre Colissimo, de votre Chronopost, de votre Lettre Prioritaire, de votre Lettre MAX ou de votre Lettre Recommandée");
});

var poll = function () {

	function _init() {
		$("#f_sondage").submit(function(){
			var identifiantPoll= $('#identifiantPoll').val();
			var answer=$(this).find("input[name='answer']:radio:checked");
			var idAnswer=answer.val();
			//xt_med('C',s2,xtpage+'::'+nettoyer_marqueur(answer.siblings('label:first').text()),'N');
			if (idAnswer>0) {
				$('#retourResult').load("/ServiceBarometre/addAnswer/(id)/1",{idAnswer:idAnswer},
				function(){
					$('#retourResultatResult').load("/ServiceBarometre/getResultat/(id)/1",{idPoll:identifiantPoll},function(){
						$('#retourResultatResult img[src$=.png]').ifixpng();
					});
					$("#retourResult").show();
					$("#f_sondage").find(":submit").css('visibility','hidden');
				});
			}
			return false;
		});
	};
	return {init:_init}
}();

var pngBgForIe = function () {
	var _init = function () {
		if (($.browser.msie && $.browser.version < 7)) {
			var regxp = new  RegExp('url\(([a-zA-Z0-9:/.-_]{1,})\)');
			$('.bottom').each(BG2Img);
		}
	}

	var BG2Img = function () {
		var regxp = new  RegExp('.png');
		var src = $(this).css('background-image');
		var res;
		if (regxp.test(src)) {
			regxp.compile('url\((.+)\)');

			res = regxp.exec(src);
			src = res[1].replace('(','');
			src = src.replace(')','');
			src = src.replace('"','');
			src = src.replace('"','');

			var img = new Image();
			img.src=src

			$(this).css('background-image','none');
			$(this).css('paddingBottom',0);
			$(this).append(img);


			$(this).find('img:last').ifixpng();

		}
	}

	return {init:_init};
}();

var lisa = function () {

	var lisaAccueil = new SWFObject("/design/laposte/images/swf/Lisa_home_anim_1.swf", "LisaHome", "600", "520", "7");
	var lisaListe 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_2.swf", "LisaHome", "600", "520", "7");
	//var lisaSuivi 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_3.swf", "LisaHome", "600", "520", "7");
	var lisaSuivi 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_3.swf", "LisaHomeCalcul", "715", "680", "7");
	//var lisaCalcul 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_4.swf", "LisaHome", "600", "520", "7");
	var lisaCalcul 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_4.swf", "LisaHomeCalcul", "715", "680", "7");
	//var lisaBdp 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_5.swf", "LisaHome", "600", "520", "7");
	var lisaBdp 	= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_5.swf", "LisaHomeBdp", "715", "680", "7");
	//var lisaCp 		= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_6.swf", "LisaHome", "600", "520", "7");
	var lisaCp 		= new SWFObject("/design/laposte/images/swf/Lisa_home_anim_6.swf", "LisaHomeCp", "715", "680", "7");
	var lisaStandby = new SWFObject("/design/laposte/images/swf/Lisa_home_standby.swf", "LisaHome", "208", "430", "7");

	var id_blockLisa = 'lisa';

	var _init = function () {
		_lisa_accueil();
	};

	var _lisa_accueil = function () {
		$('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		lisaAccueil.addParam("wmode", "transparent");
		lisaAccueil.write(id_blockLisa);
	};

	var _lisa_liste = function () {
		if($('#lisa').hasClass('LisasHomeSuivi')) $('#lisa').removeClass('LisasHomeSuivi').addClass('LisasHome');
		else if($('#lisa').hasClass('LisasHomeCalcul')) $('#lisa').removeClass('LisasHomeCalcul').addClass('LisasHome');
		else if($('#lisa').hasClass('LisasHomeBdp')) $('#lisa').removeClass('LisasHomeBdp').addClass('LisasHome');
		else if($('#lisa').hasClass('LisasHomeCp')) $('#lisa').removeClass('LisasHomeCp').addClass('LisasHome');
		else $('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		lisaListe.addParam("wmode", "transparent");
		lisaListe.write(id_blockLisa);
	};

	var _lisa_suivi = function () {
		//$('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		$('#lisa').removeClass('LisaAttente').addClass('LisasHomeSuivi');
		lisaSuivi.addParam("wmode", "transparent");
		lisaSuivi.write(id_blockLisa);
	};

	var _lisa_calcul = function () {
		//$('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		$('#lisa').removeClass('LisaAttente').addClass('LisasHomeCalcul');
		lisaCalcul.addParam("wmode", "transparent");
		lisaCalcul.write(id_blockLisa);
	};

	var _lisa_bdp = function () {
		//$('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		$('#lisa').removeClass('LisaAttente').addClass('LisasHomeBdp');
		lisaBdp.addParam("wmode", "transparent");
		lisaBdp.write(id_blockLisa);
	};

	var _lisa_cp = function () {
		//$('#lisa').removeClass('LisaAttente').addClass('LisasHome');
		$('#lisa').removeClass('LisaAttente').addClass('LisasHomeCp');
		lisaCp.addParam("wmode", "transparent");
		lisaCp.write(id_blockLisa);
	};

	var _lisa_standby = function () {
		if($('#lisa').hasClass('LisasHomeSuivi')) $('#lisa').removeClass('LisasHomeSuivi').addClass('LisaAttente');
		else if($('#lisa').hasClass('LisasHomeCalcul')) $('#lisa').removeClass('LisasHomeCalcul').addClass('LisaAttente');
		else if($('#lisa').hasClass('LisasHomeBdp')) $('#lisa').removeClass('LisasHomeBdp').addClass('LisaAttente');
		else if($('#lisa').hasClass('LisasHomeCp')) $('#lisa').removeClass('LisasHomeCp').addClass('LisaAttente');
		else $('#lisa').removeClass('LisasHome').addClass('LisaAttente');
		lisaStandby.addParam("wmode", "transparent");
		lisaStandby.write(id_blockLisa);
	};

	return {init:_init,lisa_liste:_lisa_liste,lisa_cp:_lisa_cp,lisa_bdp:_lisa_bdp,lisa_calcul:_lisa_calcul,lisa_suivi:_lisa_suivi,lisa_accueil:_lisa_accueil,lisa_standby:_lisa_standby};
}();

var nouscontacter = function () {
	var _init =function () {
		var test = $('#q_reclamation');

		$('#f_reclamation').submit(function () {

			if ($('#q_reclamation option:selected').val() == "")
			{
				return false;
			}

			var page = nettoyer_marqueur($('#q_reclamation option:selected').text());
			xt_med('C',s2, xtpage+'::formulaire_reclamation::'+ page,'N');
			return nouscontacter.openform_popup(test)});
	};

	var _openform_popup = function (elt_select) {
		if (elt_select.val() == '')
			return false;
		var currentTime=new Date();
		window.open(elt_select.val(),"name"+currentTime.getHours()+currentTime.getMinutes()+currentTime.getSeconds());
		return false;
	};
	return {init:_init, openform_popup:_openform_popup};
}();

var contactPlus = function(){
	function init(){
		$('.SavoirPlusBas').before('<a href="#" class="fermer"><img src="/design/laposte/images/conso_v2/btn_fermer.gif" alt="Fermer le cadre d\'informations" width="14" height="14" /></a>');
		$('.plusMontrer').click(function(){
			var plus = getPlus($(this));
			if (!plus.is('.plusVisible')) {
				plusFixer(plus);
				plusMontrer(plus);
			}
			return false;
		});

		$('.fermer').click(function(){
			var plus = getPlus($(this));
			if (plus.is('.plusVisible')) {
				plusRelacher(plus);
				plusCacher(plus);
			}
			return false;
		});
	}

	function getPlus(elmt){
		return elmt.parents('.contactTelItem').find('.contactSavoirPlus');
	}

	// gérer l'affichage
	function plusMontrer(elmt){
		elmt.addClass('plusVisible');
	}
	function plusCacher(elmt){
		if (!$.data(elmt.get(0),'fixe')) elmt.removeClass('plusVisible');
	}

	// pouroivr fixer l'affichage au clic
	function plusFixer(elmt){
		$.data(elmt.get(0),'fixe',true)
	}
	function plusRelacher(elmt){
		$.data(elmt.get(0),'fixe',false)
	}

	return {init:init};
}();

var liensEvitement = function (){
	var liste, liens;
	function _init(){
		liste = $('#sc_liensEvitemment').addClass('sc_hidden');
		liens = $('a', liste);
		liens.focus(function(){
			if (liste.is('.sc_hidden')) {
				liste.removeClass('sc_hidden');
				liste.show().css('height','auto');
			}
		});
	}
	return {init:_init};
}();

var partager = function() {
	var partager, deplier, sites, user;
	function _init(){

		partager = $('#partagerBas').prepend('<a href="#" id="partagerDeplier"><img src="/design/laposte/images/conso_v2/partager/partagerDeplier.gif" alt="Voir tous les moyens de partager cette page" width="19" height="19" title="Voir tous les moyens de partager cette page" /></a>');

		deplier = $('#partagerDeplier');
		sites = $('li', partager);

		user = SocialHistory();

		var listOfVisitedSites = user.visitedSites();
		listOfVisitedSites.push('Favoris');
		var numberOfVisitedSites = listOfVisitedSites.length;

		if (numberOfVisitedSites < 5) {
			listOfVisitedSites.push('Facebook');
			listOfVisitedSites.push('Twitter');
			numberOfVisitedSites = listOfVisitedSites.length;
		}

		if (numberOfVisitedSites) {
			if (numberOfVisitedSites > 5) numberOfVisitedSites = 5;
			for (var i = 0; i < numberOfVisitedSites; i++) {
				var site = listOfVisitedSites[i];
				$('img[alt='+site+']').parents('li').show().css('display','block').addClass('siteVisited');
			}
		}

		deplier.click(function(){

			var img = deplier.find('img');
			if (img.attr('src') == '/design/laposte/images/conso_v2/partager/partagerDeplier.gif') {
				img.attr('src', '/design/laposte/images/conso_v2/partager/partagerReplier.gif').attr('title', 'Ne plus voir que les moyens de partager cette page que vous avez déjà visité');
				sites.filter(':hidden').show('slow');
				$('#partager').animate({
					width: '353px'
				});
				$('#partagerListe').animate({
					width: '255px'
				});
				$('#partagerHaut').addClass('deplier');
				$('#partagerBas').addClass('deplier');
			} else {
				img.attr('src', '/design/laposte/images/conso_v2/partager/partagerDeplier.gif').attr('title', 'Voir tous les moyens de partager cette page');
				sites.not('.siteVisited').hide('slow');
				$('#partager').animate({
					width: '223px'
				});
				$('#partagerListe').animate({
					width: '136px'
				});
				$('#partagerHaut').removeClass('deplier');
				$('#partagerBas').removeClass('deplier');
			}
			return false;
		});
	}
	return {init:_init}
}();

var ongletsRecherche = function() {
	var blocOutils, nav, navLinks, navLinkDefault, navLinksWithOverlay, tabs, overlay, cloneContainer;
	var hasOverlay = false;

	function _init() {
		blocOutils = $('#outilsConso');
		nav = $('.outilsTOCItem');
		navLinks = $('.outilsTOCLink');
		navLinkDefault = $('#outilTOCSuiviEnvois .outilsTOCLink');
		navLinksWithOverlay = navLinks.not(navLinkDefault);
		tabs = $('.outilsListeItem');

		addCloseButtons(tabs.not(':first').hide().find('.outilListeContenu'));

		addOverlayCode();
		delegateClickToCloseButton();

		navLinks.click(function(clickEvent){
			clickEvent.preventDefault();
			var elmt = $(this);
			var target = hasOverlay ? $(elmt.attr('href'), overlay) : $(elmt.attr('href'));

			nav.removeClass('outilsTOCItemSelected');

			elmt.parents('.outilsTOCItem').addClass('outilsTOCItemSelected');
			if (hasOverlay) {
				$('#'+elmt.parents('.outilsTOCItem').attr('id'), overlay).addClass('outilsTOCItemSelected');
			}

			tabs.hide();
			target.show();
		});

		navLinkDefault.click(function(clickEvent){
			clickEvent.preventDefault();
			overlay.removeClass('outilsOverlayVisible');
			$('.overlayToc', overlay).remove();
			$('#outilSuiviEnvois').show();
		});

		navLinksWithOverlay.click(function(clickEvent){
			clickEvent.preventDefault();
			overlay.addClass('outilsOverlayVisible');
			addOverlaysToClonedToc(overlay);
		});

		tabsContentManagement.init();
	}

	function addCloseButtons(elmt) {
		if (elmt.find('.outilClose').size()) return;
		elmt.prepend('<p class="outilClose"><a href="#">Fermer&nbsp;<span class="outilCloseImg"></span></a></p>');
	}

	function addOverlayCode() {
		var body = $('body');

		body.append('<div id="outilsOverlay"><div id="outilsOverlayVoile"><div id="outilsCloneContainer"></div></div></div>');

		overlay = $('#outilsOverlay');
		voile = $('#outilsOverlayVoile');
		cloneContainer = $('#outilsCloneContainer');

		hasOverlay = true;

		setOverlayHeight();

		cloneBlocOutils();
		cloneContainer.find('h2').remove();

		function cloneBlocOutils() {
			clone = blocOutils.clone('true');
			clone.find('script').remove();
			clone.appendTo(cloneContainer);

			nav = $('.outilsTOCItem');
			navLinks = $('.outilsTOCLink');
			navLinksWithOverlay = navLinks.not(navLinkDefault);
			tabs = $('.outilsListeItem');
		}

		loadingLogoPrefetch();
	}

	function setOverlayHeight() {
		var documentHeight = document.body.offsetHeight+100;
		var overlayHeight = $('#outilsCloneContainer').height()+300;
		var height = documentHeight > overlayHeight ? documentHeight : overlayHeight;
		if (ltie7) voile.height(height+'px');
		else voile.css('min-height', height+'px');
	}

	function delegateClickToCloseButton() {
		$('body').delegate('.outilClose > a', 'click', function(clickEvent){
			clickEvent.preventDefault();
			navLinkDefault.click();
		});
	}

	function addOverlaysToClonedToc(elmt) {
		elmt.find('.outilsTOCItem').not('.outilsTOCItemSelected').append('<span class="overlayToc"></span>');
	}

	var tabsContentManagement = function(){

		function _init() {
			scroll.init();

			CalculTarifs.init();
			bureauPoste.init();
			CodePostal.init();
		}
		return {init:_init}
	}();

	var scroll = function() {
		var widgets;
		var ltie9 = false; /******/

		function _init() {
			widgets = $('#outilsOverlay .sc_widgetFond');

			if (ltie9) {
				if (!ltie8) {
					widgets.css({
						overflowY: 'auto',
						overflowX: 'hidden'
					});
				}
				return; // ça fait planter IE8-, donc on prend une scrollbar classique dans ce cas.
			}

			widgets.each(function(){
				var elmt = $(this);
				addScrollPane(elmt);
			});
		}

		function addScrollPane(elmt) {
			elmt.jScrollPane({
				showArrows: true,
				maintainPosition: true
			});

			handleClicks(elmt);

		}

		function handleClicks(elmt) {
			var jspObject = elmt.data('jsp');
			elmt.find(':radio').live('click', function(){
				window.setTimeout(doredraw, 50);
			});
			elmt.find(':checkbox').live('click', function(){
				window.setTimeout(doredraw, 50);
			});
			elmt.find(':submit').live('click', function(){
				window.setTimeout(doredraw, 50);
			});
			elmt.find(':text').live('blur', function(){
				window.setTimeout(doredraw, 50);
			});
			elmt.find('select').live('change', function(){
				window.setTimeout(doredraw, 50);
			});

			function doredraw() {
				redraw(jspObject);
			}
		}

		function redraw(object) {
			if (ltie9) {
				return;
			}

			if (!object.reinitialise) {
				if (object.is) {
					if (object.is('.jspPane')) {
						object = object.parents('.sc_widgetFond');
					}

					if (object.is('.sc_widgetFond')) {
						object = object.data('jsp');
					}
				}
			}

			if(object.reinitialise) {
				object.reinitialise();
			}
		}

		return {init:_init, redraw:redraw}
	}();

	function loading(elmt) {
		elmt.html('<p id="outilChargement"><img src="/design/laposte/images/conso_v2/loadinfo.gif" alt="Chargement" title="Chargement" width="24" height="24" /></p>');
	}

	function loadingLogoPrefetch() {
		var img = document.createElement("img");
		img.src = '/design/laposte/images/conso_v2/loadinfo.gif';
	}

	var CalculTarifs = function() {
		var tab, content, verifFunctionResult, form;
		function _init(){
			tab = $('#outilTOCCalculTarifs');
			content = hasOverlay ? $('#outilsOverlay #outilCalculTarifs .sc_widgetFond') : $('#outilCalculTarifs .sc_widgetFond');
			if (content.find('.jspPane').size()) {
				content = content.find('.jspPane');
			}

			tab.click(function(){
				setupCalculTarifForm();
			});
		}

		function setupCalculTarifForm(post) {
			loading(content);
			scroll.redraw(content);
			addCloseButtons(content.parents('.outilListeContenu'));

			content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Calculez-le-tarif-de-vos-envois #centre', post, function(){

				form = $('#calcTarif');

				cleanLoadedContent();
				setOverlayHeight();
				content.css({'top': 0});
				scroll.redraw(content);

				addScript('/design/laposte/javascript/tarifs.js', content);

				if (typeof(calculer_tarif_verifForm) == 'function') {
					legacy_calculer_tarif_verifForm = calculer_tarif_verifForm;
					calculer_tarif_verifForm = function() {verifFunctionResult = legacy_calculer_tarif_verifForm();}
				}

				$('#calcTarif').submit(function(submitEvent){
					submitEvent.preventDefault();
					calcTarifSubmit();
					return false;
				});

				$('#retour input, #new_search a').click(function(){
					content.css({'top': 0});
					scroll.redraw(content);
				});

				function cleanLoadedContent() {
					form.unwrap();
					form.prevAll('h1').remove();
					form.nextAll('.grand_zoom').remove();
					content.prepend("<h3>Calculez le tarif de vos envois au départ de France jusqu'à 3&nbsp;kg pour un courrier et 30&nbsp;kg pour un colis</h3>");
				}

				form.find(':radio').click(function(){
					setOverlayHeight();
				});

				$('.linkPopIn').click(function (e) {
						e.preventDefault();
						scroll.redraw(content);
					});

				$('.linkPopInOff').click(function (e) {
					e.preventDefault();
					scroll.redraw(content);
				})


			});
		}

		function calcTarifSubmit(){
			if (verifFunctionResult) {
				var post = buildPostParam();

				//return false;

				loading(content);
				scroll.redraw(content);
				content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Calculez-le-tarif-de-vos-envois #centre', post, function(){
					form = $('#calcTarif');

					cleanLoadedContent();

					setOverlayHeight();
					content.css({'top': 0});
					$('#resumerRecherche .radio_back').adjustSize()
					scroll.redraw(content);

					$('#actions').show();

					$('#new_search a').click(function(clickEvent) {
						clickEvent.preventDefault();
						content.empty();
						setupCalculTarifForm();
					});

					$('#calcTarif_retour').submit(function(submitEvent) {
						submitEvent.preventDefault();
						form = $(this);
						var post = buildPostParam();
						setupCalculTarifForm(post);
					});

					function cleanLoadedContent() {
						form.unwrap();
						form.prevAll('h1').remove();
						form.nextAll('.grand_zoom').remove();
					}
				});
			}
		}

		function buildPostParam(){
			var post = {};
			var inputsEnabled = form.find(':input').filter(':enabled');
			var checkboxes = inputsEnabled.filter(':checked');
			var selects = inputsEnabled.filter('select');

			var texts = inputsEnabled.filter(':text');
			var hidden = form.find('[type=hidden]');
			var elmts = checkboxes.add(selects).add(texts).add(hidden);

			if (!elmts.size()) {
				return '';
			}

			for (var i = 0; i < elmts.size(); i++) {
				var name = elmts.eq(i).attr('name');
				var value = elmts.eq(i).val();

				if (value) {
					post[name] = value;
				}
			}
			return post;
		}

		return {init:_init}
	}();

	var bureauPoste = function(){
		var tab, content;
		function _init(){
			tab = $('#outilTOCBureauPoste');
			content = hasOverlay ? $('#outilsOverlay #outilBureauPoste .sc_widgetFond') : $('#outilBureauPoste .sc_widgetFond');
			if (content.find('.jspPane').size()) {
				content = content.find('.jspPane');
			}

			tab.click(function(){
				var tab = $(this);

				loading(content);
				scroll.redraw(content);
				addCloseButtons(content.parents('.outilListeContenu'));

				content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Services-de-localisation/Un-bureau-de-poste #centerform', function(){

					form = $('#centerform', content);

					formatContent();

					content.prepend("<h3>Localisez un bureau de poste</h3>");
					content.find('h3').show();
					content.append('<div class="clear"></div>');
					content.css({'top': 0});
					scroll.redraw(content);

					if (typeof(tcp_ValidFormulaire) == 'function') {
						tcp_ValidFormulaire = function(){
							var OK;
							OK = true;
							if (($('#commune').val().length == 0) && ($('#cp').val().length == 0)) {
								OK = false;
								tcp_CriteresInvalides();
							} else {
								if (($('#commune').val().length != 0) && ($('#cp').val().length != 0)) {
									if ($('#cp').val().length < 2)  {
										OK = false;
										tcp_CriteresInvalides();
									}
								} else {
									if ($('#commune').val().length != 0)  {
										if ($('#commune').val().length < 3)  {
											OK = false;
											tcp_CriteresInvalides();
										}
									} else {
										if ($('#cp').val().length < 3)  {
											OK = false;
											tcp_CriteresInvalides();
										}
									}
								}
							}

							if (OK) form.submit();
							else $('#cp').focus();
						}
					}

					form.submit(function(submitEvent){
						submitEvent.preventDefault();
						bureauPosteSubmit();
					});

				});
			});
		}

		function bureauPosteSubmit() {
			var post = buildPostParam();
			loading(content);
			scroll.redraw(content);
			content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Services-de-localisation/Un-bureau-de-poste #centre', post, function(){
				formatContent(content);
				formatResultats();

				content.prepend("<h3>Localisez un bureau de poste</h3>");
				content.find('h3').show();

				setOverlayHeight();
				content.css({'top': 0});
				scroll.redraw(content);

				nouvelleRecherche();

				$('.infobureau_pad a').click(function(clickEvent) {
					clickEvent.preventDefault();
					loadBureauInfo($(this));
				});

			});
		}

		function formatResultats() {
			content.find('tr:even:not(:first)').addClass('pair');
		}

		function nouvelleRecherche() {
			var elmt = $('#lancerlarecherche');
			elmt.click(function(){
				tab.click();
			});
		}

		function loadBureauInfo(elmt){
			var href = elmt.attr('href');
			loading(content);
			scroll.redraw(content);
			content.load(href+' #resultatRecherche', function(){
				formatContent(content);
				formaterFicheBureau();
				setOverlayHeight();
				content.css({'top': 0});
				scroll.redraw(content);

				loadGoogleMapsApi();

			});
		}

		function formaterFicheBureau() {
			content
				.find('.pImgHaut').remove().end()
				.find('.gImgHaut').remove().end()
				.prepend('<h3>Résultats de votre recherche…</h3>')
				.find('h3').show().end()
				.find('.sc_widgetElement').prepend('<p><strong>Voici les détails concernant le bureau de poste que vous cherchez</strong></p>')
					.find('.moneo').insertBefore('.resultatBureau').end().end()
					.find('.resultatBureau')
						.append('<span class="resultatBureauHaut"></span>')
						.append('<span class="resultatBureauBas"></span>')
					.end()
					.find('.periode')
						.each(function(){
							var elmt = $(this);
							elmt.next('ul').andSelf().wrapAll('<div class="horaire"></div>');
						})
						.append('<span class="coinHG"></span>')
						.append('<span class="coinHD"></span>')
						.append('<span class="coinBG"></span>')
						.append('<span class="coinBD"></span>')
					.end()
					.find('.horaire')
						.adjustSize().filter(':odd').addClass('horaireImpair').end()
						.find('li').each(function(){
							var elmt = $(this);
							elmt.find('span').addClass('jour');
							elmt.html('<span class="heures">'+elmt.html()+'</span>');
							elmt.find('.jour').prependTo(elmt);
						})
						.end()
					.end()
					.find('.telephone').remove()
					.end()
					.find('.servicesTitle').each(function(){
						var elmt = $(this);
						elmt.next('ul').andSelf().wrapAll('<div class="servicesWrapper"></div>');
					}).end()
					.find('.servicesWrapper')
						.insertAfter('#googleMap')
						.find('li')
							.adjustSize().filter(':odd').addClass('serviceImpair')
							.end()
						.end()
					.append('<div class="clear"></div>')
					.append('<div id="telServiceConso"><img src="/design/laposte/images/conso_v2/bureauDePoste/numServiceConso.gif" alt="Service consommateur&nbsp;: 3631 (Appel gratuit depuis un fixe)" width="87" height="36" /></div>')
					.find('#telServiceConso')
						.append('<span class="coinHG"></span>')
						.append('<span class="coinHD"></span>')
						.append('<span class="coinBG"></span>')
						.append('<span class="coinBD"></span>');

			if (ltie7) {
				content.find('img[src$=.png]').ifixpng();
			}
		}

		function loadGoogleMapsApi() {
			content.append('<script src="http://maps.google.com/maps/api/js?sensor=false&callback=ongletsRecherche.initializeGoogleMap" type="text/javascript"></script>');
		}

		function initializeGoogleMap() {
			var myLatlng = new google.maps.LatLng($('#resultatRecherche .latitude').val(), $('#resultatRecherche .longitude').val());
			var myOptions = {
				zoom: 15,
				center: myLatlng,
				mapTypeId: google.maps.MapTypeId.ROADMAP
			}
			var map = new google.maps.Map(document.getElementById("googleMap"), myOptions);

			var image = '/design/laposte/images/img/bureau_poste/logo_laposte.png';
			var beachMarker = new google.maps.Marker({
				position: myLatlng,
				map: map,
				icon: image
			});
		}

		function buildPostParam(){
			var post = {};
			var inputsEnabled = form.find(':input').filter(':enabled');
			var checkboxes = inputsEnabled.filter(':checked');
			var selects = inputsEnabled.filter(':selected');
			var texts = inputsEnabled.filter(':text');
			var hidden = form.find('[type=hidden]');
			var elmts = checkboxes.add(selects).add(texts).add(hidden);

			if (!elmts.size()) {
				return '';
			}

			for (var i = 0; i < elmts.size(); i++) {
				var name = elmts.eq(i).attr('name');
				var value = elmts.eq(i).val();

				if (value) {
					post[name] = value;
				}
			}

			return post;
		}

		function formatContent(content) {
			if (content == undefined) {
				content = form;
			}

			$('h1', content).remove();
			$('#menu_secondaire', content).remove();
			content.find('#centre').children().unwrap();

			var contenu = content.children();
			content.append('<div class="sc_widgetElement"></div>');
			content.find('.sc_widgetElement')
				.append(contenu)
				.append('<div class="sc_widgetElementBas"></div>')
				.append('<div class="sc_widgetElementHaut"></div>');
			content.find('#lancerlarecherche').appendTo(content).after('<div class="clear"></div>');

			content.find('.ptext br').remove();

			$('#outilCodePostal').find('h3').remove();
		}

		return {init:_init, initializeGoogleMap:initializeGoogleMap}
	}();

	var CodePostal = function(){
		var tab, content, form;
		function _init(){
			tab = $('#outilTOCCodePostal');
			content = hasOverlay ? $('#outilsOverlay #outilCodePostal .sc_widgetFond') : $('#outilCodePostal .sc_widgetFond');
			if (content.find('.jspPane').size()) {
				content = content.find('.jspPane');
			}

			tab.click(function(){
				var tab = $(this);

				loading(content);
				scroll.redraw(content);
				addCloseButtons(content.parents('.outilListeContenu'));

				content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal #centerform', function(){
					form = $('#centerform', content);

					formatContent();

					if (!content.find('h3').size()) {
						content.prepend("<h3>Trouvez un code postal, un code <abbr>CEDEX</abbr> ou une commune</h3>");
					}
					content.find('h3').show();
					content.append('<div class="clear"></div>');

					setOverlayHeight();

					content.css({'top': 0});
					scroll.redraw(content);

					if (typeof(tcp_ValidFormulaire) == 'function') {
						tcp_ValidFormulaire = function(){
							var OK;
							OK = true;
							if (($('#commune').val().length == 0) && ($('#cp').val().length == 0)) {
								OK = false;
								tcp_CriteresInvalides();
							} else {
								if (($('#commune').val().length != 0) && ($('#cp').val().length != 0)) {
									if ($('#cp').val().length < 2)  {
										OK = false;
										tcp_CriteresInvalides();
									}
								} else {
									if ($('#commune').val().length != 0)  {
										if ($('#commune').val().length < 3)  {
											OK = false;
											tcp_CriteresInvalides();
										}
									} else {
										if ($('#cp').val().length < 3)  {
											OK = false;
											tcp_CriteresInvalides();
										}
									}
								}
							}

							if (OK) form.submit();
							else $('#cp').focus();
						}
					}

					form.submit(function(submitEvent){
						submitEvent.preventDefault();
						codePostalSubmit();
					});
				});
			});
		}

		function codePostalSubmit(){
			var post = buildPostParam();
			loading(content);
			scroll.redraw(content);
			content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal #centre', post, function(){
				formatContent(content);

				formatResultats();

				content.prepend("<h3>Trouvez un code postal, un code <abbr>CEDEX</abbr> ou une commune</h3>");
				content.find('h3').show();

				setOverlayHeight();
				content.css({'top': 0});
				scroll.redraw(content);

				form = $('#postalCodeResearchId');

				form.submit(function(submitEvent){
					submitEvent.preventDefault();
					codePostalStreetSubmit();
				});

				nouvelleRecherche();

			});
		}

		function formatContent(content) {
			if (content == undefined) {
				content = form;
			}

			$('h1', content).remove();
			$('#menu_secondaire', content).remove();
			content.find('#centre').children().unwrap();

			var contenu = content.children();

			content.append('<div class="sc_widgetElement"></div>');
			content.find('.sc_widgetElement')
				.append(contenu)
				.append('<div class="sc_widgetElementBas"></div>')
				.append('<div class="sc_widgetElementHaut"></div>');
			content.find('#lancerlarecherche').appendTo(content).after('<div class="clear"></div>');

			content.find('.ptext br').remove();

			$('#outilCodePostal').find('h3').prependTo(content).show();
		}

		function formatResultats() {
			content.find('tr:even:not(:first)').addClass('pair');
		}

		function codePostalStreetSubmit() {
			var post = buildPostParam();
			loading(content);
			scroll.redraw(content);
			content.load('/layout/set/ajax/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal', post, function() {
				formatContent(content);
				content.prepend("<h3>Trouvez un code postal, un code <abbr>CEDEX</abbr> ou une commune</h3>");
				content.find('h3').show();
				formatResultats();
				setOverlayHeight();
				content.css({'top': 0});
				scroll.redraw(content);

				nouvelleRecherche();

			});
		}

		function buildPostParam(){
			var post = {};
			var inputsEnabled = form.find(':input').filter(':enabled');
			var checkboxes = inputsEnabled.filter(':checked');
			var selects = inputsEnabled.filter('select');
			var texts = inputsEnabled.filter(':text');
			var hidden = form.find('[type=hidden]');
			var elmts = checkboxes.add(selects).add(texts).add(hidden);

			if (!elmts.size()) {
				return '';
			}

			for (var i = 0; i < elmts.size(); i++) {
				var name = elmts.eq(i).attr('name');
				var value = elmts.eq(i).val();

				if (value) {
					post[name] = value;
				}
			}

			return post;
		}

		function nouvelleRecherche() {
			$('#lancerlarecherche').click(function(){
				tab.click();
			});
		}

		return {init:_init}
	}();

	function addScript(src, target) {
		if ($('script[src$="'+src+'"]').size()) {
			$('script[src$="'+src+'"]').remove();
		}

		target.append('<script src="'+src+'"></script>');
	}

	function addStyle(src, target) {
		if ($('link[href='+src+']').size()) {
			return;
		}

		target.append('<link rel="stylesheet" href="'+src+'" media="all" type="text/css" />');
	}

	return {init:_init, initializeGoogleMap:bureauPoste.initializeGoogleMap};
}();

/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 * Thanks to: Seamus Leahy for adding deltaX and deltaY
 *
 * Version: 3.0.4
 *
 * Requires: 1.2.2+
 */

(function($) {

var types = ['DOMMouseScroll', 'mousewheel'];

$.event.special.mousewheel = {
	setup: function() {
		if ( this.addEventListener ) {
			for ( var i=types.length; i; ) {
				this.addEventListener( types[--i], handler, false );
			}
		} else {
			this.onmousewheel = handler;
		}
	},

	teardown: function() {
		if ( this.removeEventListener ) {
			for ( var i=types.length; i; ) {
				this.removeEventListener( types[--i], handler, false );
			}
		} else {
			this.onmousewheel = null;
		}
	}
};

$.fn.extend({
	mousewheel: function(fn) {
		return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
	},

	unmousewheel: function(fn) {
		return this.unbind("mousewheel", fn);
	}
});

function handler(event) {
	var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
	event = $.event.fix(orgEvent);
	event.type = "mousewheel";

	// Old school scrollwheel delta
	if ( event.wheelDelta ) { delta = event.wheelDelta/120; }
	if ( event.detail) { delta = -event.detail/3; }

	// New school multidimensional scroll (touchpads) deltas
	deltaY = delta;

	// Gecko
	if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
		deltaY = 0;
		deltaX = -1*delta;
	}

	// Webkit
	if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
	if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }

	// Add event and delta to the front of the arguments
	args.unshift(event, delta, deltaX, deltaY);

	return $.event.handle.apply(this, args);
}

})(jQuery);
/*!
 * jScrollPane - v2.0.0beta9 - 2011-01-31
 * http://jscrollpane.kelvinluck.com/
 *
 * Copyright (c) 2010 Kelvin Luck
 * Dual licensed under the MIT and GPL licenses.
 */

// Script: jScrollPane - cross browser customisable scrollbars
//
// *Version: 2.0.0beta9, Last updated: 2011-01-31*
//
// Project Home - http://jscrollpane.kelvinluck.com/
// GitHub - http://github.com/vitch/jScrollPane
// Source - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js
// (Minified) - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.min.js
//
// About: License
//
// Copyright (c) 2010 Kelvin Luck
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://jscrollpane.kelvinluck.com/MIT-LICENSE.txt
// http://jscrollpane.kelvinluck.com/GPL-LICENSE.txt
//
// About: Examples
//
// All examples and demos are available through the jScrollPane example site at:
// http://jscrollpane.kelvinluck.com/
//
// About: Support and Testing
//
// This plugin is tested on the browsers below and has been found to work reliably on them. If you run
// into a problem on one of the supported browsers then please visit the support section on the jScrollPane
// website (http://jscrollpane.kelvinluck.com/) for more information on getting support. You are also
// welcome to fork the project on GitHub if you can contribute a fix for a given issue.
//
// jQuery Versions - tested in 1.4.2+ - reported to work in 1.3.x
// Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8
//
// About: Release History
//
// 2.0.0beta9 - (2011-01-31) new API methods, bug fixes and correct keyboard support for FF/OSX
// 2.0.0beta8 - (2011-01-29) touchscreen support, improved keyboard support
// 2.0.0beta7 - (2011-01-23) scroll speed consistent (thanks Aivo Paas)
// 2.0.0beta6 - (2010-12-07) scrollToElement horizontal support
// 2.0.0beta5 - (2010-10-18) jQuery 1.4.3 support, various bug fixes
// 2.0.0beta4 - (2010-09-17) clickOnTrack support, bug fixes
// 2.0.0beta3 - (2010-08-27) Horizontal mousewheel, mwheelIntent, keyboard support, bug fixes
// 2.0.0beta2 - (2010-08-21) Bug fixes
// 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden
//							 elements and dynamically sized elements.
// 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated

(function($,window,undefined){

	$.fn.jScrollPane = function(settings)
	{
		// JScrollPane "class" - public methods are available through $('selector').data('jsp')
		function JScrollPane(elem, s)
		{
			var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,
				percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,
				verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,
				verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,
				horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,
				reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousContentWidth,
				wasAtTop = true, wasAtLeft = true, wasAtBottom = false, wasAtRight = false,
				originalElement = elem.clone().empty(),
				mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp' : 'mousewheel.jsp';

			originalPadding = elem.css('paddingTop') + ' ' +
								elem.css('paddingRight') + ' ' +
								elem.css('paddingBottom') + ' ' +
								elem.css('paddingLeft');
			originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft'), 10) || 0) +
										(parseInt(elem.css('paddingRight'), 10) || 0);

			function initialise(s)
			{

				var clonedElem, tempWrapper, /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,
						hasContainingSpaceChanged, originalScrollTop, originalScrollLeft;

				settings = s;

				if (pane === undefined) {
					originalScrollTop = elem.scrollTop();
					originalScrollLeft = elem.scrollLeft();
					elem.css(
						{
							overflow: 'hidden',
							padding: 0
						}
					);
					// TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should
					// come back to it later and check once it is unhidden...
					paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
					paneHeight = elem.innerHeight();

					elem.width(paneWidth);

					pane = $('<div class="jspPane" />').css('padding', originalPadding).append(elem.children());
					container = $('<div class="jspContainer" />')
						.css({
							'width': paneWidth + 'px',
							'height': paneHeight + 'px'
						}
					).append(pane).appendTo(elem);

					/*
					// Move any margins from the first and last children up to the container so they can still
					// collapse with neighbouring elements as they would before jScrollPane
					firstChild = pane.find(':first-child');
					lastChild = pane.find(':last-child');
					elem.css(
						{
							'margin-top': firstChild.css('margin-top'),
							'margin-bottom': lastChild.css('margin-bottom')
						}
					);
					firstChild.css('margin-top', 0);
					lastChild.css('margin-bottom', 0);
					*/
				} else {
					elem.css('width', '');

					hasContainingSpaceChanged = elem.innerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;

					if (hasContainingSpaceChanged) {
						paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
						paneHeight = elem.innerHeight();
						container.css({
							width: paneWidth + 'px',
							height: paneHeight + 'px'
						});
					}

					// If nothing changed since last check...
					if (!hasContainingSpaceChanged && previousContentWidth == contentWidth && pane.outerHeight() == contentHeight) {
						elem.width(paneWidth);
						return;
					}
					previousContentWidth = contentWidth;

					pane.css('width', '');
					elem.width(paneWidth);

					container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();
				}

				// Unfortunately it isn't that easy to find out the width of the element as it will always report the
				// width as allowed by its container, regardless of overflow settings.
				// A cunning workaround is to clone the element, set its position to absolute and place it in a narrow
				// container. Now it will push outwards to its maxium real width...
				clonedElem = pane.clone().css('position', 'absolute');
				tempWrapper = $('<div style="width:1px; position: relative;" />').append(clonedElem);
				$('body').append(tempWrapper);
				contentWidth = Math.max(pane.outerWidth(), clonedElem.outerWidth());
				tempWrapper.remove();

				contentHeight = pane.outerHeight();
				percentInViewH = contentWidth / paneWidth;
				percentInViewV = contentHeight / paneHeight;
				isScrollableV = percentInViewV > 1;

				isScrollableH = percentInViewH > 1;

				//console.log(paneWidth, paneHeight, contentWidth, contentHeight, percentInViewH, percentInViewV, isScrollableH, isScrollableV);

				if (!(isScrollableH || isScrollableV)) {
					elem.removeClass('jspScrollable');
					pane.css({
						top: 0,
						width: container.width() - originalPaddingTotalWidth
					});
					removeMousewheel();
					removeFocusHandler();
					removeKeyboardNav();
					removeClickOnTrack();
					unhijackInternalLinks();
				} else {
					elem.addClass('jspScrollable');

					isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
					if (isMaintainingPositon) {
						lastContentX = contentPositionX();
						lastContentY = contentPositionY();
					}

					initialiseVerticalScroll();
					initialiseHorizontalScroll();
					resizeScrollbars();

					if (isMaintainingPositon) {
						scrollToX(lastContentX, false);
						scrollToY(lastContentY, false);
					}

					initFocusHandler();
					initMousewheel();
					initTouch();

					if (settings.enableKeyboardNavigation) {
						initKeyboardNav();
					}
					if (settings.clickOnTrack) {
						initClickOnTrack();
					}

					observeHash();
					if (settings.hijackInternalLinks) {
						hijackInternalLinks();
					}
				}

				if (settings.autoReinitialise && !reinitialiseInterval) {
					reinitialiseInterval = setInterval(
						function()
						{
							initialise(settings);
						},
						settings.autoReinitialiseDelay
					);
				} else if (!settings.autoReinitialise && reinitialiseInterval) {
					clearInterval(reinitialiseInterval);
				}

				originalScrollTop && elem.scrollTop(0) && scrollToY(originalScrollTop, false);
				originalScrollLeft && elem.scrollLeft(0) && scrollToX(originalScrollLeft, false);

				elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
			}

			function initialiseVerticalScroll()
			{
				if (isScrollableV) {

					container.append(
						$('<div class="jspVerticalBar" />').append(
							$('<div class="jspCap jspCapTop" />'),
							$('<div class="jspTrack" />').append(
								$('<div class="jspDrag" />').append(
									$('<div class="jspDragTop" />'),
									$('<div class="jspDragBottom" />')
								)
							),
							$('<div class="jspCap jspCapBottom" />')
						)
					);

					verticalBar = container.find('>.jspVerticalBar');
					verticalTrack = verticalBar.find('>.jspTrack');
					verticalDrag = verticalTrack.find('>.jspDrag');

					if (settings.showArrows) {
						arrowUp = $('<a class="jspArrow jspArrowUp" />').bind(
							'mousedown.jsp', getArrowScroll(0, -1)
						).bind('click.jsp', nil);
						arrowDown = $('<a class="jspArrow jspArrowDown" />').bind(
							'mousedown.jsp', getArrowScroll(0, 1)
						).bind('click.jsp', nil);
						if (settings.arrowScrollOnHover) {
							arrowUp.bind('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
							arrowDown.bind('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
						}

						appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
					}

					verticalTrackHeight = paneHeight;
					container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(
						function()
						{
							verticalTrackHeight -= $(this).outerHeight();
						}
					);


					verticalDrag.hover(
						function()
						{
							verticalDrag.addClass('jspHover');
						},
						function()
						{
							verticalDrag.removeClass('jspHover');
						}
					).bind(
						'mousedown.jsp',
						function(e)
						{
							// Stop IE from allowing text selection
							$('html').bind('dragstart.jsp selectstart.jsp', nil);

							verticalDrag.addClass('jspActive');

							var startY = e.pageY - verticalDrag.position().top;

							$('html').bind(
								'mousemove.jsp',
								function(e)
								{
									positionDragY(e.pageY - startY, false);
								}
							).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
							return false;
						}
					);
					sizeVerticalScrollbar();
				}
			}

			function sizeVerticalScrollbar()
			{
				verticalTrack.height(verticalTrackHeight + 'px');
				verticalDragPosition = 0;
				scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();

				// Make the pane thinner to allow for the vertical scrollbar
				pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);

				// Add margin to the left of the pane if scrollbars are on that side (to position
				// the scrollbar on the left or right set it's left or right property in CSS)
				if (verticalBar.position().left === 0) {
					pane.css('margin-left', scrollbarWidth + 'px');
				}
			}

			function initialiseHorizontalScroll()
			{
				if (isScrollableH) {

					container.append(
						$('<div class="jspHorizontalBar" />').append(
							$('<div class="jspCap jspCapLeft" />'),
							$('<div class="jspTrack" />').append(
								$('<div class="jspDrag" />').append(
									$('<div class="jspDragLeft" />'),
									$('<div class="jspDragRight" />')
								)
							),
							$('<div class="jspCap jspCapRight" />')
						)
					);

					horizontalBar = container.find('>.jspHorizontalBar');
					horizontalTrack = horizontalBar.find('>.jspTrack');
					horizontalDrag = horizontalTrack.find('>.jspDrag');

					if (settings.showArrows) {
						arrowLeft = $('<a class="jspArrow jspArrowLeft" />').bind(
							'mousedown.jsp', getArrowScroll(-1, 0)
						).bind('click.jsp', nil);
						arrowRight = $('<a class="jspArrow jspArrowRight" />').bind(
							'mousedown.jsp', getArrowScroll(1, 0)
						).bind('click.jsp', nil);
						if (settings.arrowScrollOnHover) {
							arrowLeft.bind('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));
							arrowRight.bind('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
						}
						appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
					}

					horizontalDrag.hover(
						function()
						{
							horizontalDrag.addClass('jspHover');
						},
						function()
						{
							horizontalDrag.removeClass('jspHover');
						}
					).bind(
						'mousedown.jsp',
						function(e)
						{
							// Stop IE from allowing text selection
							$('html').bind('dragstart.jsp selectstart.jsp', nil);

							horizontalDrag.addClass('jspActive');

							var startX = e.pageX - horizontalDrag.position().left;

							$('html').bind(
								'mousemove.jsp',
								function(e)
								{
									positionDragX(e.pageX - startX, false);
								}
							).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
							return false;
						}
					);
					horizontalTrackWidth = container.innerWidth();
					sizeHorizontalScrollbar();
				}
			}

			function sizeHorizontalScrollbar()
			{
				container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(
					function()
					{
						horizontalTrackWidth -= $(this).outerWidth();
					}
				);

				horizontalTrack.width(horizontalTrackWidth + 'px');
				horizontalDragPosition = 0;
			}

			function resizeScrollbars()
			{
				if (isScrollableH && isScrollableV) {
					var horizontalTrackHeight = horizontalTrack.outerHeight(),
						verticalTrackWidth = verticalTrack.outerWidth();
					verticalTrackHeight -= horizontalTrackHeight;
					$(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(
						function()
						{
							horizontalTrackWidth += $(this).outerWidth();
						}
					);
					horizontalTrackWidth -= verticalTrackWidth;
					paneHeight -= verticalTrackWidth;
					paneWidth -= horizontalTrackHeight;
					horizontalTrack.parent().append(
						$('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px')
					);
					sizeVerticalScrollbar();
					sizeHorizontalScrollbar();
				}
				// reflow content
				if (isScrollableH) {
					pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
				}
				contentHeight = pane.outerHeight();
				percentInViewV = contentHeight / paneHeight;

				if (isScrollableH) {
					horizontalDragWidth = Math.ceil(1 / percentInViewH * horizontalTrackWidth);
					if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
						horizontalDragWidth = settings.horizontalDragMaxWidth;
					} else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
						horizontalDragWidth = settings.horizontalDragMinWidth;
					}
					horizontalDrag.width(horizontalDragWidth + 'px');
					dragMaxX = horizontalTrackWidth - horizontalDragWidth;
					_positionDragX(horizontalDragPosition); // To update the state for the arrow buttons
				}
				if (isScrollableV) {
					verticalDragHeight = Math.ceil(1 / percentInViewV * verticalTrackHeight);
					if (verticalDragHeight > settings.verticalDragMaxHeight) {
						verticalDragHeight = settings.verticalDragMaxHeight;
					} else if (verticalDragHeight < settings.verticalDragMinHeight) {
						verticalDragHeight = settings.verticalDragMinHeight;
					}
					verticalDrag.height(verticalDragHeight + 'px');
					dragMaxY = verticalTrackHeight - verticalDragHeight;
					_positionDragY(verticalDragPosition); // To update the state for the arrow buttons
				}
			}

			function appendArrows(ele, p, a1, a2)
			{
				var p1 = "before", p2 = "after", aTemp;

				// Sniff for mac... Is there a better way to determine whether the arrows would naturally appear
				// at the top or the bottom of the bar?
				if (p == "os") {
					p = /Mac/.test(navigator.platform) ? "after" : "split";
				}
				if (p == p1) {
					p2 = p;
				} else if (p == p2) {
					p1 = p;
					aTemp = a1;
					a1 = a2;
					a2 = aTemp;
				}

				ele[p1](a1)[p2](a2);
			}

			function getArrowScroll(dirX, dirY, ele)
			{
				return function()
				{
					arrowScroll(dirX, dirY, this, ele);
					this.blur();
					return false;
				};
			}

			function arrowScroll(dirX, dirY, arrow, ele)
			{
				arrow = $(arrow).addClass('jspActive');

				var eve,
					scrollTimeout,
					isFirst = true,
					doScroll = function()
					{
						if (dirX !== 0) {
							jsp.scrollByX(dirX * settings.arrowButtonSpeed);
						}
						if (dirY !== 0) {
							jsp.scrollByY(dirY * settings.arrowButtonSpeed);
						}
						scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.arrowRepeatFreq);
						isFirst = false;
					};

				doScroll();

				eve = ele ? 'mouseout.jsp' : 'mouseup.jsp';
				ele = ele || $('html');
				ele.bind(
					eve,
					function()
					{
						arrow.removeClass('jspActive');
						scrollTimeout && clearTimeout(scrollTimeout);
						scrollTimeout = null;
						ele.unbind(eve);
						focusElem();
					}
				);
			}

			function initClickOnTrack()
			{
				removeClickOnTrack();
				if (isScrollableV) {
					verticalTrack.bind(
						'mousedown.jsp',
						function(e)
						{
							if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
								var clickedTrack = $(this),
									offset = clickedTrack.offset(),
									direction = e.pageY - offset.top - verticalDragPosition,
									scrollTimeout,
									isFirst = true,
									doScroll = function()
									{
										var offset = clickedTrack.offset(),
											pos = e.pageY - offset.top - verticalDragHeight / 2,
											contentDragY = paneHeight * settings.scrollPagePercent,
											dragY = dragMaxY * contentDragY / (contentHeight - paneHeight);
										if (direction < 0) {
											if (verticalDragPosition - dragY > pos) {
												jsp.scrollByY(-contentDragY);
											} else {
												positionDragY(pos);
											}
										} else if (direction > 0) {
											if (verticalDragPosition + dragY < pos) {
												jsp.scrollByY(contentDragY);
											} else {
												positionDragY(pos);
											}
										} else {
											cancelClick();
											return;
										}
										scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
										isFirst = false;
									},
									cancelClick = function()
									{
										scrollTimeout && clearTimeout(scrollTimeout);
										scrollTimeout = null;
										$(document).unbind('mouseup.jsp', cancelClick);
										focusElem();
									};
								doScroll();
								$(document).bind('mouseup.jsp', cancelClick);
								return false;
							}
						}
					);
				}

				if (isScrollableH) {
					horizontalTrack.bind(
						'mousedown.jsp',
						function(e)
						{
							if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
								var clickedTrack = $(this),
									offset = clickedTrack.offset(),
									direction = e.pageX - offset.left - horizontalDragPosition,
									scrollTimeout,
									isFirst = true,
									doScroll = function()
									{
										var offset = clickedTrack.offset(),
											pos = e.pageX - offset.left - horizontalDragWidth / 2,
											contentDragX = paneWidth * settings.scrollPagePercent,
											dragX = dragMaxX * contentDragX / (contentWidth - paneWidth);
										if (direction < 0) {
											if (horizontalDragPosition - dragX > pos) {
												jsp.scrollByX(-contentDragX);
											} else {
												positionDragX(pos);
											}
										} else if (direction > 0) {
											if (horizontalDragPosition + dragX < pos) {
												jsp.scrollByX(contentDragX);
											} else {
												positionDragX(pos);
											}
										} else {
											cancelClick();
											return;
										}
										scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
										isFirst = false;
									},
									cancelClick = function()
									{
										scrollTimeout && clearTimeout(scrollTimeout);
										scrollTimeout = null;
										$(document).unbind('mouseup.jsp', cancelClick);
										focusElem();
									};
								doScroll();
								$(document).bind('mouseup.jsp', cancelClick);
								return false;
							}
						}
					);
				}
			}

			function removeClickOnTrack()
			{
				if (horizontalTrack) {
					horizontalTrack.unbind('mousedown.jsp');
				}
				if (verticalTrack) {
					verticalTrack.unbind('mousedown.jsp');
				}
			}

			function cancelDrag()
			{
				$('html').unbind('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');

				if (verticalDrag) {
					verticalDrag.removeClass('jspActive');
				}
				if (horizontalDrag) {
					horizontalDrag.removeClass('jspActive');
				}
				focusElem();
			}

			function positionDragY(destY, animate)
			{
				if (!isScrollableV) {
					return;
				}
				if (destY < 0) {
					destY = 0;
				} else if (destY > dragMaxY) {
					destY = dragMaxY;
				}

				// can't just check if(animate) because false is a valid value that could be passed in...
				if (animate === undefined) {
					animate = settings.animateScroll;
				}
				if (animate) {
					jsp.animate(verticalDrag, 'top', destY,	_positionDragY);
				} else {
					verticalDrag.css('top', destY);
					_positionDragY(destY);
				}

			}

			function _positionDragY(destY)
			{
				if (destY === undefined) {
					destY = verticalDrag.position().top;
				}

				container.scrollTop(0);
				verticalDragPosition = destY;

				var isAtTop = verticalDragPosition === 0,
					isAtBottom = verticalDragPosition == dragMaxY,
					percentScrolled = destY/ dragMaxY,
					destTop = -percentScrolled * (contentHeight - paneHeight);

				if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
					wasAtTop = isAtTop;
					wasAtBottom = isAtBottom;
					elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
				}

				updateVerticalArrows(isAtTop, isAtBottom);
				pane.css('top', destTop);
				elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]).trigger('scroll');
			}

			function positionDragX(destX, animate)
			{
				if (!isScrollableH) {
					return;
				}
				if (destX < 0) {
					destX = 0;
				} else if (destX > dragMaxX) {
					destX = dragMaxX;
				}

				if (animate === undefined) {
					animate = settings.animateScroll;
				}
				if (animate) {
					jsp.animate(horizontalDrag, 'left', destX,	_positionDragX);
				} else {
					horizontalDrag.css('left', destX);
					_positionDragX(destX);
				}
			}

			function _positionDragX(destX)
			{
				if (destX === undefined) {
					destX = horizontalDrag.position().left;
				}

				container.scrollTop(0);
				horizontalDragPosition = destX;

				var isAtLeft = horizontalDragPosition === 0,
					isAtRight = horizontalDragPosition == dragMaxX,
					percentScrolled = destX / dragMaxX,
					destLeft = -percentScrolled * (contentWidth - paneWidth);

				if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
					wasAtLeft = isAtLeft;
					wasAtRight = isAtRight;
					elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
				}

				updateHorizontalArrows(isAtLeft, isAtRight);
				pane.css('left', destLeft);
				elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]).trigger('scroll');
			}

			function updateVerticalArrows(isAtTop, isAtBottom)
			{
				if (settings.showArrows) {
					arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');
					arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');
				}
			}

			function updateHorizontalArrows(isAtLeft, isAtRight)
			{
				if (settings.showArrows) {
					arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');
					arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');
				}
			}

			function scrollToY(destY, animate)
			{
				var percentScrolled = destY / (contentHeight - paneHeight);
				positionDragY(percentScrolled * dragMaxY, animate);
			}

			function scrollToX(destX, animate)
			{
				var percentScrolled = destX / (contentWidth - paneWidth);
				positionDragX(percentScrolled * dragMaxX, animate);
			}

			function scrollToElement(ele, stickToTop, animate)
			{
				var e, eleHeight, eleWidth, eleTop = 0, eleLeft = 0, viewportTop, maxVisibleEleTop, maxVisibleEleLeft, destY, destX;

				// Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
				// errors from the lookup...
				try {
					e = $(ele);
				} catch (err) {
					return;
				}
				eleHeight = e.outerHeight();
				eleWidth= e.outerWidth();

				container.scrollTop(0);
				container.scrollLeft(0);

				// loop through parents adding the offset top of any elements that are relatively positioned between
				// the focused element and the jspPane so we can get the true distance from the top
				// of the focused element to the top of the scrollpane...
				while (!e.is('.jspPane')) {
					eleTop += e.position().top;
					eleLeft += e.position().left;
					e = e.offsetParent();
					if (/^body|html$/i.test(e[0].nodeName)) {
						// we ended up too high in the document structure. Quit!
						return;
					}
				}

				viewportTop = contentPositionY();
				maxVisibleEleTop = viewportTop + paneHeight;
				if (eleTop < viewportTop || stickToTop) { // element is above viewport
					destY = eleTop - settings.verticalGutter;
				} else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewport
					destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
				}
				if (destY) {
					scrollToY(destY, animate);
				}

				viewportLeft = contentPositionX();
				maxVisibleEleLeft = viewportLeft + paneWidth;
				if (eleLeft < viewportLeft || stickToTop) { // element is to the left of viewport
					destX = eleLeft - settings.horizontalGutter;
				} else if (eleLeft + eleWidth > maxVisibleEleLeft) { // element is to the right viewport
					destX = eleLeft - paneWidth + eleWidth + settings.horizontalGutter;
				}
				if (destX) {
					scrollToX(destX, animate);
				}

			}

			function contentPositionX()
			{
				return -pane.position().left;
			}

			function contentPositionY()
			{
				return -pane.position().top;
			}

			function initMousewheel()
			{
				container.unbind(mwEvent).bind(
					mwEvent,
					function (event, delta, deltaX, deltaY) {
						var dX = horizontalDragPosition, dY = verticalDragPosition;
						jsp.scrollBy(deltaX * settings.mouseWheelSpeed, -deltaY * settings.mouseWheelSpeed, false);
						// return true if there was no movement so rest of screen can scroll
						return dX == horizontalDragPosition && dY == verticalDragPosition;
					}
				);
			}

			function removeMousewheel()
			{
				container.unbind(mwEvent);
			}

			function nil()
			{
				return false;
			}

			function initFocusHandler()
			{
				pane.find(':input,a').unbind('focus.jsp').bind(
					'focus.jsp',
					function(e)
					{
						scrollToElement(e.target, false);
					}
				);
			}

			function removeFocusHandler()
			{
				pane.find(':input,a').unbind('focus.jsp');
			}

			function initKeyboardNav()
			{
				var keyDown, elementHasScrolled;
				// IE also focuses elements that don't have tabindex set.
				pane.focus(
					function()
					{
						elem.focus();
					}
				);

				elem.attr('tabindex', 0)
					.unbind('keydown.jsp keypress.jsp')
					.bind(
						'keydown.jsp',
						function(e)
						{
							if (e.target !== this){
								return;
							}
							var dX = horizontalDragPosition, dY = verticalDragPosition;
							switch(e.keyCode) {
								case 40: // down
								case 38: // up
								case 34: // page down
								case 32: // space
								case 33: // page up
								case 39: // right
								case 37: // left
									keyDown = e.keyCode;
									keyDownHandler();
									break;
								case 35: // end
									scrollToY(contentHeight - paneHeight);
									keyDown = null;
									break;
								case 36: // home
									scrollToY(0);
									keyDown = null;
									break;
							}

							elementHasScrolled = e.keyCode == keyDown && dX != horizontalDragPosition || dY != verticalDragPosition;
							return !elementHasScrolled;
						}
					).bind(
						'keypress.jsp', // For FF/ OSX so that we can cancel the repeat key presses if the JSP scrolls...
						function(e)
						{
							if (e.keyCode == keyDown) {
								keyDownHandler();
							}
							return !elementHasScrolled;
						}
					);

				if (settings.hideFocus) {
					elem.css('outline', 'none');
					if ('hideFocus' in container[0]){
						elem.attr('hideFocus', true);
					}
				} else {
					elem.css('outline', '');
					if ('hideFocus' in container[0]){
						elem.attr('hideFocus', false);
					}
				}

				function keyDownHandler()
				{
					var dX = horizontalDragPosition, dY = verticalDragPosition;
					switch(keyDown) {
						case 40: // down
							jsp.scrollByY(settings.keyboardSpeed, false);
							break;
						case 38: // up
							jsp.scrollByY(-settings.keyboardSpeed, false);
							break;
						case 34: // page down
						case 32: // space
							jsp.scrollByY(paneHeight * settings.scrollPagePercent, false);
							break;
						case 33: // page up
							jsp.scrollByY(-paneHeight * settings.scrollPagePercent, false);
							break;
						case 39: // right
							jsp.scrollByX(settings.keyboardSpeed, false);
							break;
						case 37: // left
							jsp.scrollByX(-settings.keyboardSpeed, false);
							break;
					}

					elementHasScrolled = dX != horizontalDragPosition || dY != verticalDragPosition;
					return elementHasScrolled;
				}
			}

			function removeKeyboardNav()
			{
				elem.attr('tabindex', '-1')
					.removeAttr('tabindex')
					.unbind('keydown.jsp keypress.jsp');
			}

			function observeHash()
			{
				if (location.hash && location.hash.length > 1) {
					var e, retryInt;
					try {
						e = $(location.hash);
					} catch (err) {
						return;
					}

					if (e.length && pane.find(location.hash)) {
						// nasty workaround but it appears to take a little while before the hash has done its thing
						// to the rendered page so we just wait until the container's scrollTop has been messed up.
						if (container.scrollTop() === 0) {
							retryInt = setInterval(
								function()
								{
									if (container.scrollTop() > 0) {
										scrollToElement(location.hash, true);
										$(document).scrollTop(container.position().top);
										clearInterval(retryInt);
									}
								},
								50
							);
						} else {
							scrollToElement(location.hash, true);
							$(document).scrollTop(container.position().top);
						}
					}
				}
			}

			function unhijackInternalLinks()
			{
				$('a.jspHijack').unbind('click.jsp-hijack').removeClass('jspHijack');
			}

			function hijackInternalLinks()
			{
				unhijackInternalLinks();
				$('a[href^=#]').addClass('jspHijack').bind(
					'click.jsp-hijack',
					function()
					{
						var uriParts = this.href.split('#'), hash;
						if (uriParts.length > 1) {
							hash = uriParts[1];
							if (hash.length > 0 && pane.find('#' + hash).length > 0) {
								scrollToElement('#' + hash, true);
								// Need to return false otherwise things mess up... Would be nice to maybe also scroll
								// the window to the top of the scrollpane?
								return false;
							}
						}
					}
				);
			}

			// If no element has focus, focus elem to support keyboard navigation
			function focusElem()
			{
				if (!$(':focus').length) {
					elem.focus();
				}
			}

			// Init touch on iPad, iPhone, iPod, Android
			function initTouch()
			{
				var startX,
					startY,
					touchStartX,
					touchStartY,
					moved,
					moving = false;

				container.unbind('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').bind(
					'touchstart.jsp',
					function(e)
					{
						var touch = e.originalEvent.touches[0];
						startX = contentPositionX();
						startY = contentPositionY();
						touchStartX = touch.pageX;
						touchStartY = touch.pageY;
						moved = false;
						moving = true;
					}
				).bind(
					'touchmove.jsp',
					function(ev)
					{
						if(!moving) {
							return;
						}

						var touchPos = ev.originalEvent.touches[0],
							dX = horizontalDragPosition, dY = verticalDragPosition;

						jsp.scrollTo(startX + touchStartX - touchPos.pageX, startY + touchStartY - touchPos.pageY);

						moved = moved || Math.abs(touchStartX - touchPos.pageX) > 5 || Math.abs(touchStartY - touchPos.pageY) > 5;

						// return true if there was no movement so rest of screen can scroll
						return dX == horizontalDragPosition && dY == verticalDragPosition;
					}
				).bind(
					'touchend.jsp',
					function(e)
					{
						moving = false;
						/*if(moved) {
							return false;
						}*/
					}
				).bind(
					'click.jsp-touchclick',
					function(e)
					{
						if(moved) {
							moved = false;
							return false;
						}
					}
				);
			}

			function destroy(){
				var currentY = contentPositionY(),
					currentX = contentPositionX();
				elem.removeClass('jspScrollable').unbind('.jsp');
				elem.replaceWith(originalElement.append(pane.children()));
				originalElement.scrollTop(currentY);
				originalElement.scrollLeft(currentX);
			}

			// Public API
			$.extend(
				jsp,
				{
					// Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it
					// was initialised). The settings object which is passed in will override any settings from the
					// previous time it was initialised - if you don't pass any settings then the ones from the previous
					// initialisation will be used.
					reinitialise: function(s)
					{
						s = $.extend({}, settings, s);
						initialise(s);
					},
					// Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so
					// that it can be seen within the viewport. If stickToTop is true then the element will appear at
					// the top of the viewport, if it is false then the viewport will scroll as little as possible to
					// show the element. You can also specify if you want animation to occur. If you don't provide this
					// argument then the animateScroll value from the settings object is used instead.
					scrollToElement: function(ele, stickToTop, animate)
					{
						scrollToElement(ele, stickToTop, animate);
					},
					// Scrolls the pane so that the specified co-ordinates within the content are at the top left
					// of the viewport. animate is optional and if not passed then the value of animateScroll from
					// the settings object this jScrollPane was initialised with is used.
					scrollTo: function(destX, destY, animate)
					{
						scrollToX(destX, animate);
						scrollToY(destY, animate);
					},
					// Scrolls the pane so that the specified co-ordinate within the content is at the left of the
					// viewport. animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					scrollToX: function(destX, animate)
					{
						scrollToX(destX, animate);
					},
					// Scrolls the pane so that the specified co-ordinate within the content is at the top of the
					// viewport. animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					scrollToY: function(destY, animate)
					{
						scrollToY(destY, animate);
					},
					// Scrolls the pane to the specified percentage of its maximum horizontal scroll position. animate
					// is optional and if not passed then the value of animateScroll from the settings object this
					// jScrollPane was initialised with is used.
					scrollToPercentX: function(destPercentX, animate)
					{
						scrollToX(destPercentX * (contentWidth - paneWidth), animate);
					},
					// Scrolls the pane to the specified percentage of its maximum vertical scroll position. animate
					// is optional and if not passed then the value of animateScroll from the settings object this
					// jScrollPane was initialised with is used.
					scrollToPercentY: function(destPercentY, animate)
					{
						scrollToY(destPercentY * (contentHeight - paneHeight), animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollBy: function(deltaX, deltaY, animate)
					{
						jsp.scrollByX(deltaX, animate);
						jsp.scrollByY(deltaY, animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollByX: function(deltaX, animate)
					{
						var destX = contentPositionX() + deltaX,
							percentScrolled = destX / (contentWidth - paneWidth);
						positionDragX(percentScrolled * dragMaxX, animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollByY: function(deltaY, animate)
					{
						var destY = contentPositionY() + deltaY,
							percentScrolled = destY / (contentHeight - paneHeight);
						positionDragY(percentScrolled * dragMaxY, animate);
					},
					// Positions the horizontal drag at the specified x position (and updates the viewport to reflect
					// this). animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					positionDragX: function(x, animate)
					{
						positionDragX(x, animate);
					},
					// Positions the vertical drag at the specified y position (and updates the viewport to reflect
					// this). animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					positionDragY: function(y, animate)
					{
						positionDragX(y, animate);
					},
					// This method is called when jScrollPane is trying to animate to a new position. You can override
					// it if you want to provide advanced animation functionality. It is passed the following arguments:
					//  * ele		- the element whose position is being animated
					//  * prop		- the property that is being animated
					//  * value		- the value it's being animated to
					//  * stepCallback - a function that you must execute each time you update the value of the property
					// You can use the default implementation (below) as a starting point for your own implementation.
					animate: function(ele, prop, value, stepCallback)
					{
						var params = {};
						params[prop] = value;
						ele.animate(
							params,
							{
								'duration'	: settings.animateDuration,
								'ease'		: settings.animateEase,
								'queue'		: false,
								'step'		: stepCallback
							}
						);
					},
					// Returns the current x position of the viewport with regards to the content pane.
					getContentPositionX: function()
					{
						return contentPositionX();
					},
					// Returns the current y position of the viewport with regards to the content pane.
					getContentPositionY: function()
					{
						return contentPositionY();
					},
					// Returns the width of the content within the scroll pane.
					getContentWidth: function()
					{
						return contentWidth();
					},
					// Returns the height of the content within the scroll pane.
					getContentHeight: function()
					{
						return contentHeight();
					},
					// Returns the horizontal position of the viewport within the pane content.
					getPercentScrolledX: function()
					{
						return contentPositionX() / (contentWidth - paneWidth);
					},
					// Returns the vertical position of the viewport within the pane content.
					getPercentScrolledY: function()
					{
						return contentPositionY() / (contentHeight - paneHeight);
					},
					// Returns whether or not this scrollpane has a horizontal scrollbar.
					getIsScrollableH: function()
					{
						return isScrollableH;
					},
					// Returns whether or not this scrollpane has a vertical scrollbar.
					getIsScrollableV: function()
					{
						return isScrollableV;
					},
					// Gets a reference to the content pane. It is important that you use this method if you want to
					// edit the content of your jScrollPane as if you access the element directly then you may have some
					// problems (as your original element has had additional elements for the scrollbars etc added into
					// it).
					getContentPane: function()
					{
						return pane;
					},
					// Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the
					// animateScroll value from settings is used instead.
					scrollToBottom: function(animate)
					{
						positionDragY(dragMaxY, animate);
					},
					// Hijacks the links on the page which link to content inside the scrollpane. If you have changed
					// the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the
					// contents of your scroll pane will work then call this function.
					hijackInternalLinks: function()
					{
						hijackInternalLinks();
					},
					// Removes the jScrollPane and returns the page to the state it was in before jScrollPane was
					// initialised.
					destroy: function()
					{
							destroy();
					}
				}
			);

			initialise(s);
		}

		// Pluginifying code...
		settings = $.extend({}, $.fn.jScrollPane.defaults, settings);

		// Apply default speed
		$.each(['mouseWheelSpeed', 'arrowButtonSpeed', 'trackClickSpeed', 'keyboardSpeed'], function() {
			settings[this] = settings[this] || settings.speed;
		});

		var ret;
		this.each(
			function()
			{
				var elem = $(this), jspApi = elem.data('jsp');
				if (jspApi) {
					jspApi.reinitialise(settings);
				} else {
					jspApi = new JScrollPane(elem, settings);
					elem.data('jsp', jspApi);
				}
				ret = ret ? ret.add(elem) : elem;
			}
		);
		return ret;
	};

	$.fn.jScrollPane.defaults = {
		showArrows					: false,
		maintainPosition			: true,
		clickOnTrack				: true,
		autoReinitialise			: false,
		autoReinitialiseDelay		: 500,
		verticalDragMinHeight		: 0,
		verticalDragMaxHeight		: 99999,
		horizontalDragMinWidth		: 0,
		horizontalDragMaxWidth		: 99999,
		animateScroll				: false,
		animateDuration				: 300,
		animateEase					: 'linear',
		hijackInternalLinks			: false,
		verticalGutter				: 4,
		horizontalGutter			: 4,
		mouseWheelSpeed				: 0,
		arrowButtonSpeed			: 0,
		arrowRepeatFreq				: 50,
		arrowScrollOnHover			: false,
		trackClickSpeed				: 0,
		trackClickRepeatFreq		: 70,
		verticalArrowPositions		: 'split',
		horizontalArrowPositions	: 'split',
		enableKeyboardNavigation	: true,
		hideFocus					: false,
		keyboardSpeed				: 0,
		initialDelay				: 300,		// Delay before starting repeating
		speed						: 30,		// Default speed when others falsey
		scrollPagePercent			: 0.8		// Percent of visible area scrolled when pageUp/Down or track area pressed
	};

})(jQuery,this);


