/*
 * 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
 *
 * Patched Version by Jamie Thompson - Fixes IE7 Positioning Issues
 * http://jamazon.co.uk/web/2008/03/17/thickbox-31-ie7-positioning-bug/
 * Patched Version by PrestaShop - Translated fields
 * http://www.prestashop.com
*/

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

// fixes the fact that ie7 now reports itself as MSIE 6.0 compatible
$.browser.msie6 = 
        $.browser.msie 
        && /MSIE 6\.0/i.test(window.navigator.userAgent) 
        && !/MSIE 7\.0/i.test(window.navigator.userAgent);

//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;
	}).removeClass('thickbox');
}

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[@rel="+imageGroup+"]").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='#'>" + ThickboxI18nNext + "</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='#'>" + ThickboxI18nPrev + "</a></span>";
							}
						} else {
							TB_FoundURL = true;
							TB_imageCount = ThickboxI18nImage + ' ' + (TB_Counter + 1) + ' ' + ThickboxI18nOf + ' ' + (TB_TempArray.length);											
						}
				}
			}

			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("<img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='"+ThickboxI18nClose+"'>"+ThickboxI18nClose+"</a> "+ThickboxI18nOrEscKey+"</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_Image").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='"+ThickboxI18nClose+"'>"+ThickboxI18nClose+"</a> "+ThickboxI18nOrEscKey+"</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 + 29)+"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 + 29)+"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' title='"+ThickboxI18nClose+"'>"+ThickboxI18nClose+"</a> "+ThickboxI18nOrEscKey+"</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.msie6)) { // 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;
  }
}

/* idTabs ~ Sean Catchpole - Version 1.0 */ 
 
/* Options (in any order): 
 
 start (number|string) 
    Index number of default tab. ex: idTabs(0) 
    String of id of default tab. ex: idTabs("#tab1") 
    default: class "selected" or index 0 
 
 return (boolean) 
    True - Url will change. ex: idTabs(true) 
    False - Url will not change. ex: idTabs(false) 
    default: false 
 
 click (function) 
    Function will be called when a tab is clicked. ex: idTabs(foo) 
    If the function returns true, idTabs will show/hide content (as usual). 
    If the function returns false, idTabs will not take any action. 
    The function is passed three variables: 
      The id of the element to be shown 
      an array of all id's that can be shown 
      and the element containing the tabs 
*/ 
(function($){ 
  $.fn.idTabs = function(){ 
    //Defaults 
    var s = { "start":null, 
              "return":false, 
              "click":null }; 
 
    //Loop Arguments matching options 
    for(var i=0; i<arguments.length; ++i) { 
      var n = {}, a=arguments[i]; 
      switch(typeof a){ 
        case "object": $.extend(n,a); break; 
        case "number": 
        case "string": n.start = a; break; 
        case "boolean": n["return"] = a; break; 
        case "function": n.click = a; break; 
      }; $.extend(s,n); 
    } 
     
    //Setup Tabs 
    var self = this; //Save scope 
    var list = $("a[@href^='#']",this).click(function(){ 
      if($("a.selected",self)[0]==this) 
        return s["return"]; //return if already selected 
      var id = "#"+this.href.split('#')[1]; 
      var aList = []; //save tabs 
      var idList = []; //save possible elements 
      $("a",self).each(function(){ 
        if(this.href.match(/#/)) { 
          aList[aList.length]=this; 
          idList[idList.length]="#"+this.href.split('#')[1]; 
        } 
      }); 
      if(s.click && !s.click(id,idList,self)) return s["return"]; 
      //Clear tabs, and hide all 
      for(i in aList) $(aList[i]).removeClass("selected"); 
      for(i in idList) {
	      $(idList[i]).addClass('block_hidden_only_for_screen');
      }
      //Select clicked tab and show content 
      $(this).addClass("selected"); 
      $(id).removeClass('block_hidden_only_for_screen');
      return s["return"]; //Option for changing url 
    }); 
 
    //Select default tab 
    var test; 
    if(typeof s.start == "number" && (test=list.filter(":eq("+s.start+")")).length) 
      test.click(); //Select num tab 
    else if(typeof s.start == "string" && (test=list.filter("[@href='#"+s.start+"']")).length) 
      test.click(); //Select tab linking to id 
    else if((test=list.filter(".selected")).length) 
      test.removeClass("selected").click(); //Select tab with class 'selected' 
    else list.filter(":first").click(); //Select first tab 
 
    return this; //Chainable 
  }; 
  $(function(){ $(".idTabs").each(function(){ $(this).idTabs(); }); }); 
})(jQuery)
/**
 * jQuery.ScrollTo
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Date: 2/19/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * Tested with jQuery 1.2.1. On FF 2.0.0.11, IE 6, Opera 9.22 and Safari 3 beta. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.3.3
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object} settings Hash of settings, optional.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('div').scrollTo( 340 );
 *
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { offset:-20 } );
 *
 * Notes:
 *  - jQuery.scrollTo will make the whole window scroll, it accepts the same arguments as jQuery.fn.scrollTo.
 *	- If you are interested in animated anchor navigation, check http://jquery.com/plugins/project/LocalScroll.
 *	- The options margin, offset and over are ignored, if the target is not a jQuery object or a DOM element.
 *	- The option 'queue' won't be taken into account, if only 1 axis is given.
 */
;(function( $ ){

	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$scrollTo.window().scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'y',
		duration:1
	};

	//returns the element that needs to be animated to scroll the window
	$scrollTo.window = function(){
		return $( $.browser.safari ? 'body' : 'html' );
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		settings = $.extend( {}, $scrollTo.defaults, settings );
		duration = duration || settings.speed || settings.duration;//speed is still recognized for backwards compatibility
		settings.queue = settings.queue && settings.axis.length > 1;//make sure the settings are given right
		if( settings.queue )
			duration /= 2;//let's keep the overall speed, the same.
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.each(function(){
			var elem = this, $elem = $(elem),
				t = target, toff, attr = {},
				win = $elem.is('html,body');
			switch( typeof t ){
				case 'number'://will pass the regex
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(t) ){
						t = both( t );
						break;//we are done
					}
					t = $(t,this);// relative selector, no break!
				case 'object':
					if( t.is || t.style )//DOM/jQuery
						toff = (t = $(t)).offset();//get the real position of the target 
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					act = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height',
					dim = Dim.toLowerCase();

				if( toff ){//jQuery/DOM
					attr[key] = toff[pos] + ( win ? 0 : act - $elem.offset()[pos] );

					if( settings.margin ){//if it's a dom element, reduce the margin
						attr[key] -= parseInt(t.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(t.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;//add/deduct the offset
					
					if( settings.over[pos] )//scroll to a fraction of its width/height
						attr[key] += t[dim]() * settings.over[pos];
				}else
					attr[key] = t[pos];//remove the unnecesary 'px'

				if( /^\d+$/.test(attr[key]) )//number or 'number'
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );//check the limits

				if( !i && settings.queue ){//queueing each axis is required					
					if( act != attr[key] )//don't waste time animating, if there's no need.
						animate( settings.onAfterFirst );//intermediate animation
					delete attr[key];//don't animate this axis again in the next iteration.
				}
			});
			
			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target);
				});
			};
			function max( Dim ){
				var el = win ? $.browser.opera ? document.body : document.documentElement : elem;
				return el['scroll'+Dim] - el['client'+Dim];
			};
		});
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})( jQuery );
/**
 * jQuery.serialScroll
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/1/2008
 *
 * @projectDescription Animated scrolling of series.
 * @author Ariel Flesler
 * @version 1.1.0
 *
 * @id jQuery.serialScroll
 * @id jQuery.fn.serialScroll
 * @param {Object} settings Hash of settings, it is passed in to jQuery.ScrollTo, none is required.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * http://flesler.blogspot.com/2008/02/jqueryserialscroll.html
 *
 * Notes:
 *	- The plugin requires jQuery.ScrollTo.
 *	- The hash of settings, is passed to jQuery.ScrollTo, so its settings can be used as well.
 */
;(function( $ ){

	var $serialScroll = $.serialScroll = function( settings ){
		$.scrollTo.window().serialScroll( settings );
	};

	//Many of these defaults, belong to jQuery.ScrollTo, check it's demo for an example of each option.
	//@see http://www.flesler.webs/jQuery.ScrollTo/
	$serialScroll.defaults = {//the defaults are public and can be overriden.
		duration:1000, //how long to animate.
		axis:'x', //which of top and left should be scrolled
		event:'click', //on which event to react.
		start:0, //first element (zero-based index)
		step:1, //how many elements to scroll on each action
		lock:true,//ignore events if already animating
		cycle:true //cycle endlessly ( constant velocity )
		/*
		interval:0, //it's the number of milliseconds to automatically go to the next
		lazy:false,//go find the elements each time (allows AJAX or JS content, or reordering)
		stop:false, //stop any previous animations to avoid queueing
		force:false,//force the scroll to the first element on start ?
		jump: false,//if true, when the event is triggered on an element, the pane scrolls to it
		items:null, //selector to the items (relative to the matched elements)
		prev:null, //selector to the 'prev' button
		next:null, //selector to the 'next' button
		onBefore: //function called before scrolling, if it returns false, the event is ignored
		*/		
	};

	$.fn.serialScroll = function( settings ){
		settings = $.extend( {}, $serialScroll.defaults, settings );
		var event = settings.event, //this one is just to get shorter code when compressed
			step = settings.step, // idem
			duration = settings.duration / step; //save it, we'll need it

		return this.each(function(){
			var 
				$pane = $(this),
				items = settings.lazy ? settings.items : $( settings.items, $pane ),
				actual = settings.start,
				timer; //for the interval

			if( settings.force )
				jump.call( this, {}, actual );//generate an initial call

			// Button binding, optional
			$(settings.prev||[]).bind( event, -step, move );
			$(settings.next||[]).bind( event, step, move );
			
			// Custom events bound to the container
			$pane.bind('prev.serialScroll', -step, move ) //you can trigger with just 'prev'
				 .bind('next.serialScroll', step, move ) //for example: $(container).trigger('next');
				 .bind('goto.serialScroll', jump ); //for example: $(container).trigger('goto', [4] );

			if( !settings.lazy && settings.jump )//can't use jump if using lazy items
				items.bind( event, function( e ){
					e.data = items.index(this);
					jump( e, this );
				});

			function move( e ){
				e.data += actual;
				jump( e, this );
			};			
			function jump( e, button ){
				if( typeof button == 'number' ){//initial or special call from the outside $(container).trigger('goto',[index]);
					e.data = button;
					button = this;
				}

				var 
					pos = e.data, elem,
					real = e.type, //is a real event triggering ?
					$items = $(items,$pane),
					limit = $items.length;

				if( real )//real event object
					e.preventDefault();

				pos %= limit; //keep it under the limit
				if( pos < 0 )
					pos += limit;

				elem = $items[pos];

				if( settings.interval ){
					clearTimeout(timer);//clear any possible automatic scrolling.
					timer = setTimeout(function(){ $pane.trigger('next.serialScroll'); }, settings.interval ); //I'll use the namespace to avoid conflicts
				}

				if( isNaN(pos) || real && actual == pos || //could happen, save some CPU cycles in vain
					settings.lock && $pane.is(':animated') || //no animations while busy
					!settings.cycle && !$items[e.data] || //no cycling
					real && settings.onBefore && //callback returns false ?
				 	settings.onBefore.call(button, e, elem, $pane, $items, pos) === false ) return;

				if( settings.stop )
					$pane.queue('fx',[]).stop();//remove all its animations

				settings.duration = duration * Math.abs( actual - pos );//keep constant velocity
				$pane.scrollTo( elem, settings );
				actual = pos;
			};
		});
	};

})( jQuery );

//return a formatted price
function formatCurrency(price, currencyFormat, currencySign){
	//if you modified this function, don't forget to modify the PHP function displayPrice (in the Tools.php class)
	var numberOfDecimal = 2;
	if(currencyFormat == 1)
		return currencySign + formatNumber(price,numberOfDecimal,',', '.');
	if(currencyFormat == 2)
		return (formatNumber(price,numberOfDecimal,' ',',') + ' ' + currencySign);
	if(currencyFormat == 3)
		return (currencySign + ' ' + formatNumber(price,numberOfDecimal,' ',','));
	if(currencyFormat == 4)
		return (formatNumber(price,numberOfDecimal,',', '.') + currencySign);
	return price;
}

//return a formatted number
function formatNumber(value,numberOfDecimal,thousenSeparator, virgule) {
	value = value.toFixed(numberOfDecimal);
	var val_string = value+'';
	var tmp = val_string.split('.');
	var abs_val_string = (tmp.length == 2) ? tmp[0] : val_string;
	var deci_string = ('0.' + (tmp.length == 2 ? tmp[1] : 0)).substr(2);
	var nb = abs_val_string.length;
	for (var i=1;i<4;i++)
		if (value>=Math.pow(10,(3*i)))
			abs_val_string=abs_val_string.substring(0,nb-(3*i))+thousenSeparator+abs_val_string.substring(nb-(3*i));
	return abs_val_string + virgule + (deci_string > 0 ? deci_string : '00');
}

//change the text of a jQuery element with a sliding effect (velocity could be a number in ms, 'slow' or 'fast', effect1 and effect2 could be slide, fade, hide, show)
function updateTextWithEffect(jQueryElement, text, velocity, effect1, effect2, newClass)
{
	if(jQueryElement.text() != text)
		if(effect1 == 'fade')
			jQueryElement.fadeOut(velocity, function(){
				$(this).addClass(newClass);
				if(effect2 == 'fade') $(this).text(text).fadeIn(velocity);
				else if(effect2 == 'slide') $(this).text(text).slideDown(velocity);
					else if(effect2 == 'show')	$(this).text(text).show(velocity, function(){});
			});
		else if(effect1 == 'slide')
			jQueryElement.slideUp(velocity, function(){
				$(this).addClass(newClass);
				if(effect2 == 'fade') $(this).text(text).fadeIn(velocity);
				else if(effect2 == 'slide') $(this).text(text).slideDown(velocity);
					else if(effect2 == 'show')	$(this).text(text).show(velocity);
			});
			else if(effect1 == 'hide')
				jQueryElement.hide(velocity, function(){
					$(this).addClass(newClass);
					if(effect2 == 'fade') $(this).text(text).fadeIn(velocity);
					else if(effect2 == 'slide') $(this).text(text).slideDown(velocity);
						else if(effect2 == 'show')	$(this).text(text).show(velocity);
				});
}

//show a JS debug
function dbg(value){
	var active = false;//true for active
	var firefox = true;//true if debug under firefox

	if (active)
		if (firefox)
			console.log(value);
		else
			alert(value);	
}

/**
* Function : print_r()
* Arguments: The data  - array,hash(associative array),object
*            The level - OPTIONAL
* Returns  : The textual representation of the array.
* This function was inspired by the print_r function of PHP.
* This will accept some data as the argument and return a
* text that will be a more readable version of the
* array/hash/object that is given.
*/
function print_r(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

//verify if value is in the array
function in_array(value, array)
{
	for (var i in array) if (array[i] == value) return true;
	return false;
}
















	
//global variables
var combinations = new Array();
var selectedCombination = new Array();
var globalQuantity = new Number;
var colors = new Array();

//add a combination of attributes in the global JS sytem
function addCombination(idCombination, arrayOfIdAttributes, quantity, price, ecotax, id_image)
{
	globalQuantity += quantity;

	var combination = new Array();
	combination['idCombination'] = idCombination;
	combination['quantity'] = quantity;
	combination['idsAttributes'] = arrayOfIdAttributes;
	combination['price'] = price;
	combination['ecotax'] = ecotax;
	combination['image'] = id_image;
	combinations.push(combination);
}


// search the combinations' case of attributes and update displaying of availability, prices, ecotax, and image
function findCombination()
{
	//create a temporary 'choice' array containing the choices of the customer
	var choice = new Array();
	$('div#attributes select').each(function(){
		choice.push($(this).val());
	});
	var nbAttributesEquals = 0;
	//testing every combination to find the conbination's attributes' case of the user
	
	for (combination in combinations)
	{
		//verify if this combinaison is the same that the user's choice
		nbAttributesEquals = 0;
		for (idAttribute in combinations[combination]['idsAttributes'])
		{
			//ie6 bug fix
			if (idAttribute != 'indexOf'){
				//if this attribute has been choose by user
				if (in_array(combinations[combination]['idsAttributes'][idAttribute], choice))
				{
					//we are in a good way to find the good combination !
					nbAttributesEquals++;
				}
			}
		}

		if (nbAttributesEquals == choice.length)
		{
			//combination of the user has been found in our specifications of combinations (created in back office)
			selectedCombination['unavailable'] = false;
			
			$('#idCombination').val(combinations[combination]['idCombination']);

			//get the data of product with these attributes
			quantityAvailable = combinations[combination]['quantity'];
			selectedCombination['price'] = combinations[combination]['price'];
			if (combinations[combination]['ecotax'])
				selectedCombination['ecotax'] = combinations[combination]['ecotax'];
			else
				selectedCombination['ecotax'] = default_eco_tax;
			
			//show the large image in relation to the selected combination
			if (combinations[combination]['image'] && combinations[combination]['image'] != -1)
				displayImage( $('#thumb_'+combinations[combination]['image']).parent() );
			
			//update the display
			updateDisplay();
			
			//leave the function because combination has been found
			return;
		}
	}
	//this combination don't exist (not created in back office)
	selectedCombination['unavailable'] = true;
	updateDisplay();
}

function updateColorSelect(id_attribute)
{
	// Visual effect
	$('#color_'+id_attribute).fadeTo('fast', 1, function(){	$(this).fadeTo('slow', 0, function(){ $(this).fadeTo('slow', 1, function(){}); }); });
	// Attribute selection
	$('#group_'+id_color_default+' option[value='+id_attribute+']').attr('selected', 'selected');
	$('#group_'+id_color_default+' option[value!='+id_attribute+']').removeAttr('selected');
	findCombination();
}

function isdefined( variable)
{
    return (typeof(window[variable]) == "undefined")?  false: true;
}


//update display of the availability of the product AND the prices of the product
function updateDisplay()
{
	if (!selectedCombination['unavailable'] && quantityAvailable > 0)
	{
		//show the choice of quantities
		$('#quantity_wanted_p:hidden').show('slow');
		
		//show the "add to cart" button ONLY if it was hidden
		$('#add_to_cart:hidden').fadeIn(600);
		//availability value management
		if (availabilityValue != '')
		{
			//update the availability statut of the product
			$('#availability_value').removeClass('warning-inline');
			$('#availability_value').text(availabilityValue);
			$('#availability_statut:hidden').show();
		}
		else
		{
			//hide the availability value
			$('#availability_statut:visible').hide();
		}
		
		if(isdefined('maxQuantityToAllowDisplayOfLastQuantityMessage')) {
			//'last quantities' message management
			if (quantityAvailable <= maxQuantityToAllowDisplayOfLastQuantityMessage)
			{
				//display the 'last quantities' message
				$('#last_quantities').show('slow');
			}
			else
			{
				//hide the 'last quantities' message
				$('#last_quantities').hide('slow');
			}

			//display the quantities of pieces (only if allowed)
			if (quantitiesDisplayAllowed)
			{
				$('#pQuantityAvailable:hidden').show('slow');
				$('#quantityAvailable').text(quantityAvailable); 
				if(quantityAvailable < 2)
				{
					$('#quantityAvailableTxt').show();
					$('#quantityAvailableTxtMultiple').hide();
				}
				else
				{
					$('#quantityAvailableTxt').hide();
					$('#quantityAvailableTxtMultiple').show();
				}
			}

		}	
	}
	else
	{
		//hide 'last quantities' message if it was previously visible
		$('#last_quantities:visible').hide('slow');

		//hide the quantity of pieces if it was previously visible
		$('#pQuantityAvailable:visible').hide('slow');
		
		//hide the choice of quantities
		$('#quantity_wanted_p:visible').hide('slow');
		
		//display that the product is unavailable with theses attributes
		if (!selectedCombination['unavailable'])
			$('#availability_value').text(doesntExistNoMore + (globalQuantity > 0 ? ' ' + doesntExistNoMoreBut : '')).addClass('warning-inline');
		else
			$('#availability_value').text(doesntExist).addClass('warning-inline');
		$('#availability_statut:hidden').show();

		
		//show the 'add to cart' button ONLY IF it's possible to buy when out of stock AND if it was previously invisible
		if (allowBuyWhenOutOfStock && !selectedCombination['unavailable'])
		{
			$('#add_to_cart:hidden').fadeIn(600);
			$('p#availability_statut:visible').hide('slow');
		}
		else
		{
			$('#add_to_cart:visible').fadeOut(600);
			$('p#availability_statut:hidden').show('slow');
		}
	}
	
	//update display of the the prices in relation to tax, discount, ecotax, and currency criteria
	if (!selectedCombination['unavailable'])
	{
		var attribut_price_tmp = selectedCombination['price'];

		var tax = (taxRate / 100) + 1;

		if (noTaxForThisProduct)
			attribut_price_tmp /= tax;

		var productPriceWithoutReduction2 = (attribut_price_tmp + productPriceWithoutReduction) * currencyRate;
		
		if (reduction_from != reduction_to && (currentDate > reduction_to || currentDate < reduction_from))
			var priceReduct = 0;
		else
			var priceReduct = productPriceWithoutReduction2 / 100 * parseFloat(reduction_percent) + reduction_price;
		var priceProduct = productPriceWithoutReduction2 - priceReduct;
		var productPricePretaxed = (productPriceWithoutReduction2 - priceReduct) / tax;
		$('#our_price_display').text(formatCurrency(priceProduct, currencyFormat, currencySign));
		$('#pretaxe_price_display').text(formatCurrency(productPricePretaxed, currencyFormat, currencySign));
		$('#old_price_display').text(formatCurrency(productPriceWithoutReduction2, currencyFormat, currencySign));
		$('#ecotax_price_display').text(formatCurrency(selectedCombination['ecotax'], currencyFormat, currencySign));
	}
}

//update display of the large image
function displayImage(domAAroundImgThumb)
{
	if (!domAAroundImgThumb.hasClass('shown'))
	{
		if (domAAroundImgThumb.attr('href'))
		{
			var newSrc = domAAroundImgThumb.attr('href').replace('thickbox','large');
			$('#bigpic').fadeOut('fast', function(){
				$(this).attr('src', newSrc);
				$(this).fadeIn('fast');
			});
			$('#views_block li a').removeClass('shown');
			$(domAAroundImgThumb).addClass('shown');
		}
	}
}

//To do after loading HTML
$(document).ready(function(){

	if($('#thumbs_list')) {
	
		//init the serialScroll for thumbs
		$('#thumbs_list').serialScroll({
			items:'li',
			prev:'a#view_scroll_left',
			next:'a#view_scroll_right',
			axis:'x',
			offset:0,
			start:0,
			stop:true,
			duration:700,
			step: 2,
			lock: false,
			force:false,
			cycle:false
		});
	
		//hover 'other views' images management
		$('#views_block li a').hover(
			function(){displayImage($(this));},
			function(){}
		);
	
		//add a link on the span 'view full size' and on the big image
		$('span#view_full_size, div#image-block img').click(function(){
			$('#views_block li a.shown').click();
		});
	
		//catch the click on the "more infos" button at the top of the page
		$('div#short_description_block p a.button').click(function(){
			$('#more_info_tab_more_info').click();
			$.scrollTo( '#more_info_tabs', 1200 );
		});
	
		//init the price in relation of the selected attributes
		if (typeof productHasAttributes != 'undefined' && productHasAttributes)
			findCombination();
	}
});
