/* requires $ */
//$.noConflict();
//if (!window.console) console = {};
//console.log = console.log || function(){};
//console.warn = console.warn || function(){};
//console.error = console.error || function(){};
//console.info = console.info || function(){};

var SEARCH_BOX_DEFAULT_TEXT = "Keyword, Title, Author, ISBN";

// Global function, if set colorbox will scroll to href #anchor value inside div.
var colorbox_scroll_to  = null;
var colorbox_scroll_div = null;

if (typeof Sarissa != 'undefined'){
	jQuery.ajaxSetup({
		xhr: function(){
            if (typeof ActiveXObject != 'undefined'){
				return new ActiveXObject("Microsoft.XMLHTTP");
            }else if ( Sarissa.originalXMLHttpRequest){
                return new Sarissa.originalXMLHttpRequest();
			}else{
				return new XMLHttpRequest();
			}
		}
	});
}

//useful function
var utils={
		twoDigits:function(inte){
			if (inte<10) return "0" + inte;
			if (inte>99){
				var str=inte.toString();
				return str.substring(str.length-2);
			}
			return inte.toString();
		},

		dateDiff:function(date1,date2){
			var baseDate=new Date(1970,01,01);
			date1=date1||baseDate;
			date2=date2||baseDate;

			return Math.abs(date1.getTime()-date2.getTime());
		},

		RealTypeOf:function(v){
			if (typeof(v) == "object"){
				if (v === null) return "null";
				if (v.constructor == (new Array).constructor) return "array";
				if (v.constructor == (new Date).constructor) return "date";
				if (v.constructor == (new RegExp).constructor) return "regex";
				return "object";
			}
			return typeof(v);
		}
};

Date.prototype.shortDate=function(sep){ //i.e. 22/11/1989
	sep=sep||"/";
	return utils.twoDigits(this.getMonth()+1) + sep + utils.twoDigits(this.getDate()) + sep + this.getFullYear();
};

//object usefull to handle content scroll.
var scroller=function(element){
	var myDiv=$(element);

	var scrollRight=function(scrollSizeParam,duration,clearQueue,jumptoEnd){
		myDiv.stop(clearQueue||false,jumptoEnd||false);
		var scrollSize=scrollSizeParam||1;
		var width=myDiv.innerWidth();
		var availableScroll=myDiv.get(0).scrollWidth-myDiv.scrollLeft()-width;
		availableScroll=availableScroll>width*scrollSize?width*scrollSize:availableScroll;

		myDiv.animate({scrollLeft:myDiv.scrollLeft()+availableScroll},duration||500);
	};

	var scrollLeft=function(scrollSizeParam,duration,clearQueue,jumptoEnd){
		myDiv.stop(clearQueue||false,jumptoEnd||false);
		var scrollSize=scrollSizeParam||1;
		var width=myDiv.innerWidth();
		var availableScroll=myDiv.scrollLeft();
		availableScroll=availableScroll>width*scrollSize?-width*scrollSize:-availableScroll;

		myDiv.animate({scrollLeft:myDiv.scrollLeft()+availableScroll},duration||500);
	};

	var scrollUp=function(scrollSizeParam,duration){
		myDiv.stop();
		var scrollSize=scrollSizeParam||1;
		var height=myDiv.innerHeight(),
		scrollHeight=myDiv.get(0).scrollHeight;

		var availableScroll=scrollHeight-myDiv.scrollTop()-height;
		availableScroll=availableScroll>height*scrollSize?height*scrollSize:availableScroll;
		myDiv.animate({scrollTop:myDiv.scrollTop()+availableScroll},duration||500);
	};

	var scrollDown=function(scrollSizeParam,duration){
		myDiv.stop();
		var scrollSize=scrollSizeParam||1;
		var height=myDiv.innerHeight(),
		scrollHeight=myDiv.get(0).scrollHeight;

		var availableScroll=myDiv.scrollTop();
		availableScroll=availableScroll>height*scrollSize?-height*scrollSize:-availableScroll;
		myDiv.animate({scrollTop:myDiv.scrollTop()+availableScroll},duration||500);
	};

	return{
		scrollLeft:scrollLeft,
		scrollRight:scrollRight,
		scrollUp:scrollUp,
		scrollDown:scrollDown
	};
};

//ixDropDown plugin
(function($){
	$.fn.ixDropDown=function(options){
		//defining the base style for this object. Style customisation can be done by assigning a className to the <select> element
		//and then defining its rules in your CSS
		var rules=[
		           ".ixDropDown_A span{display:block}",
		           ".ixDropDown_A {display:inline-block; text-align:left; zoom: 1; *display: inline;vertical-align:bottom;outline:none}",
		           ".ixDropDown_A{ color:#069; padding-right:15px}",
		           ".ixDropDown_DIV {position:absolute; display:none;}",
			   ".ixDropDown_Cont {zoom:1}",
		           ".ixDropDown_UL {list-style-type:none; padding:0; margin:0px; outline:none}"
		           ];

		$("<style type='text/css'>" + rules.join("\n") + "</style>").appendTo("head");


		return this.each(function(){
			var thisObj=$(this).hide(0),
			timerHnd=null;

			//binding the onChange event to the <select>
			thisObj.change(function(){
				$(this).siblings("a.ixDropDown_A").find("span").text(this.options[this.selectedIndex].text);
			});

			var curOption=$.map(thisObj.find("option"),function(item, index){
				return item.selected?item:null;
			});

			curOption=curOption.length>0?curOption[0]:thisObj.children().eq(0).get(0);

			var anchor=$("<a href='#show' />")
			.insertAfter(thisObj)
			.addClass("ixDropDown_A " + this.className)
			.addClass(this.disabled?" disabled":(curOption?"":"disabled"))
			.append($("<span />").text(curOption?(curOption.label||$(curOption).text()):"- empty -"))
			.focus(function(){
				clearTimeout(timerHnd);
			})
			.blur(function(){
				//var $this=$(this);
				//timerHnd=setTimeout(function(){
					//close($this);
				//},100
				//);
			})
			.click(function(e){

				e.preventDefault();
				var $anchor=$(this);

				// Close all dropdowns already opened
				$('.ixDropDown_A.open').each(function(){
					var $this=$(this);
					if ( $this.html()!=$anchor.html() ) {
						close($this);
					}
				});


				if ($anchor.hasClass("disabled")){return false;};

				var select=$anchor.prev("select").get(0),
				externalDiv=$("<div />")
				.keydown(function(e){
					switch(e.which){
					case 40: //down
						$(document.activeElement).closest("li").nextAll().find("a").eq(0).focus();
						return false;
						break;

					case 38: //up
						$(document.activeElement).closest("li").prevAll().find("a").eq(0).focus();
						return false;
						break;
					}
				})
				.addClass("ixDropDown_DIV " + select.className),
				contDiv=$("<div />").addClass("ixDropDown_Cont").appendTo(externalDiv),
				ul=$("<ul />")
				.attr("tabIndex",-1)
				.focus(function(){
					clearTimeout(timerHnd);
				})
				.blur(function(){
					timerHnd=setTimeout(function(){
						close($anchor);
					},50
					);
				})
				.addClass("ixDropDown_UL")
				.appendTo(contDiv);

				var options=$(select).children();

				if($anchor.data("externalDiv")){
					close($anchor);
					return false;
				}

				//adding the "open" className
				$anchor.addClass("open");

				$anchor.data("externalDiv",externalDiv);

				doHTML(options);

				function doHTML(items){
					$.each(items,function(index,item){

						if(item.disabled){
							$("<span />")
							.text(item.text)
							.addClass("disabled")
							.appendTo(
									$("<li />").appendTo(ul)
							);
							return true;
						}

						switch(item.tagName.toLowerCase()){
						case "optgroup":
							$("<strong />")
							.text(item.label)
							.appendTo(
									$("<li />").appendTo(ul)
							);

							doHTML($(item).children());
							break;

						case "option":
							$("<a />")
							.text(item.text)
							.attr("href","#" + item.text)
							.attr("data_index",index)
							.click(function(e){
								e.preventDefault();

								var $this=$(this);
								var index=$this.attr("data_index");
								var option=items[index];

								option.selected="selected";

								close($anchor);

								$anchor.siblings("select").change();
							})
							.focus(function(){
								clearTimeout(timerHnd);
							})
							.blur(function(){
								timerHnd=setTimeout(function(){
									// close($anchor);
								},50
								);
							})
							.appendTo(
									$("<li />").appendTo(ul)
							);

							$('body').click(function() {
								timerHnd=setTimeout(
									function(){
							 			close($anchor);
									},50
								);
							});

							break;
						}
					});
				}

				var pos=$anchor.offset();

				externalDiv.appendTo(document.body)
				.css({
					left:pos.left,
					top:pos.top+$anchor.outerHeight(true)
				})
				.slideDown(120,function(){ul.find("a:first").focus();});

				return false;
			});
		});

		function close(anchor){
			var externalDiv=anchor.data("externalDiv");

			anchor.removeClass("open");

			if(externalDiv){
				anchor.data("externalDiv",null).focus();
				externalDiv.slideUp(120,function(){externalDiv.remove();});
			}
		}
	};

	$.fn.disabled=function(status){
		return status == undefined ? "" : status?this.addClass("disabled"):this.removeClass("disabled");
	};

})(jQuery);

(function($){
	$(document).ready(function(){
		var pixelsPerSec = 50;

        //Add mouseover and mouseout event handlers for elements with the titleScroll class
		$ ('.titleScroll').mouseover(function() {
			$(this).stop();
			var scrollTime = (($(this).innerWidth() - $(this).scrollLeft()) / pixelsPerSec) * 1000;
			$(this).animate({scrollLeft:$(this).innerWidth()}, scrollTime);
		});
		$ ('.titleScroll').mouseout(function() {
			$(this).stop();
			var scrollTime = ($(this).scrollLeft() / pixelsPerSec) * 1000;
			$(this).animate({scrollLeft:0}, scrollTime);
		});


		//overriding the setTarget function contained in the HTML code
		window.setTarget=function(target){
			$('#productSearchForm').attr('target', target);
			
			if (target != '_self') {
				$('#search-ribbon select').val('ALL_SUBJECTS');
				$('#search-ribbon select').change();
			}
			
			$('#subject-picker-set a.ixDropDown_A').disabled(target != '_self');
		};
		
		// force the browse content dropdown to default to the correct value.
		$('#browseContentForm select').val('browse_content');

		if ($.browser.msie){
			//ie layout fix
			$("#header-logo,#nav").css("zoom",1);

			// IE6 hover fix
			if ($.browser.version<7){
				$("#dropdown li").hover(
						function(){$(this).addClass("over");},
						function(){$(this).removeClass("over");}
				);
			}
		}

		if ( $("ul.tabs").length ){
			initializeProductTabs();
		};

		//transforming all the select.ixDropDown elements into ixDropDown widgets
		//$("select").ixDropDown();	
		var selectArray=[
			"#header select"
			,"#header-myaccount select"
			,"#search-ribbon select"
			,".sortby-form select"
			,"#resources-search select"
            ,"#bookResourceListForm dt select"
		];
		$(selectArray.join(",")).ixDropDown();


		setupSearchFormBehaviour();

		if ($('#content').hasClass('search-page')){
			handleSearchResultsTypeFiltering();
		}

		//remove this to activate the share-links bar
		//shareLinks.init();

		/* $-ui stuff */
		initialize$UiStuff();

		// Get all textareas that have a "maxlength" property. Now, and when later adding HTML using jQuery-scripting:
		jQuery('textarea.maxlength').live('keyup', function() {
			// Store the maxlength and value of the field.
			var re = new RegExp("(?:maxlength-)([0-9]+)");
			var matches = re.exec(this.className);
			var maxlength = matches[1];
			var val = $(this).val();
			// Trim the field if it has content over the maxlength.
			if (val.length > maxlength) {
			   $(this).val(val.slice(0, maxlength));
			}
		});



		/* Remove dotted border effect when links clicked */
		$(".tabContainer a, .accordionContainer h3").click(function(){
			this.blur();
		});

		// external links
		$('a[href][rel*=external]').each(function(i){
			this.target = "_blank";
		});
		
		initializeColorbox();

		if ($('#content').hasClass('faq-page')) initializeFaqToggles();

		/* binding toolTips events*/
		var ttElements=$("#right-column .carouselContainer a img");

		ttElements.live("mouseenter",function(){
			//creating the html for the toolTip content
			var ttContainer=$("<div></div>").addClass("container");
			var ttContent=$("<div></div>").addClass("content").appendTo(ttContainer);

			var $this=$(this),
			spanTags=$this.closest("li").children("span");

			var title = spanTags.filter('.title').text() || "--";

			if ($.browser.msie) {
				// The (.*) difference applied on IE replaces everythin with start of "<br", until the very last ">" it find in the string.
				var author = spanTags.filter('.author').text() ? spanTags.filter(".author").html().replace(/<BR>/ig,"<br/>").split("<br/>") : ["--"];
			}
			else {
				// webkit fix.. <BR> fetched by spanTags.filter('.author').text() becomes <br xmlns="http://......." /> and gets displayed on tooltips..
				var author = spanTags.filter('.author').text() ? spanTags.filter(".author").html().replace(/<BR(.*)>/ig,"<br>").split("<br>") : ["--"];
			}
			
			var date = spanTags.filter('.date').text()||"--";

			if(date != "--"){
				date=date.split(" ")[0].split("-");
				date=new Date(date[0],date[1]-1,date[2]).shortDate();
			}

			$("<p></p>")
			.text(title)
			.addClass("title")
			.appendTo(ttContent);

			var dl=$("<dl></dl>").appendTo(ttContent);

			$("<dt>Author(s):</dt>").appendTo(dl);
			$("<dd></dd>")
			.html(author.join(", "))
			.appendTo(dl);

			$("<dt>Pub Date:</dt>").appendTo(dl);
			$("<dd></dd>")
			.addClass("date")
			.text(date)
			.appendTo(dl);

			//showing the toolTip
			toolTip.show(ttContainer,this);
		});

		ttElements.live("mouseleave",function(){
			toolTip.hide();
		});
		
		// start student search section, select all checkboxes
		if ($('#resources-search-wrapper').length){
			// select all by default
			$('#resources-search-wrapper input:checkbox').attr('checked', true);
		}
		// end student search section
		
		if (document.images) { // preload 
			var preLoad=['search_blue_over','search_green_over','search_red_over'];
			var preImages=[];
			for(imgI=0;imgI<preLoad.length;imgI++) {
				preImages[imgI]     = new Image();
				preImages[imgI].src = "/_res/images/static/" + preLoad[imgI] + ".png"
			}
		}
		
	});
})(jQuery);

//share-links bar handler
var shareLinks={
		init:function(){
			//show-hide share-links bar button
			$("div.share-links a.closeBtn").toggle(
					function(){
						$(this).text("show tools").parent().addClass("closed");
					},
					function(){
						$(this).text("hide tools").parent().removeClass("closed");
					}
			);

			var links=$("div.share-links a");

			// setting the current url for Facebook and Twitter
			links.filter(".fb,.tw").each(function(){
				var linkUrl=this.hash.replace("#","")+window.location;
				this.href=linkUrl;
			});

			//customising the email button
			links.filter(".email").click(function(){
				alert ("Please add the email function!");
				return false;
			});
		}
};

/* --- tooltip object definition --- */
var toolTip=(function(){

	//private variables and functions
	var divObj=null,
	show=function(content,hoveredElem){

		if (!divObj){
			divObj=$("<div></div>")
			.attr("id","toolTip")
			.css({
				position:"absolute",
				display:"none",
				zIndex:999
			})
			.appendTo(document.body);
		}

		divObj.empty();
		divObj.append(content);

		hoveredElem=$(hoveredElem);
		var pos=hoveredElem.offset();

		divObj.css({
			left:(pos.left+hoveredElem.outerWidth()/2)-divObj.outerWidth()/2,
			top:pos.top-divObj.outerHeight(true)
		});

		divObj.show(0);

	},
	hide=function(){
		divObj.hide(0);
	};

	//public API
	return{
		show:show,
		hide:hide
	};
})();
/* ---------------------------------- */

/* scrollBar function definition */
function addScrollBar(options){
	var $=jQuery;

	var clickPos={},
	myDiv=options.elemToScroll.css("overflow","hidden"),
	horiz=options.horizontal,
	moving=false;

	//size check
	var containerSize=horiz?myDiv.innerWidth():myDiv.innerHeight(),
			contentSize=horiz?myDiv.get(0).scrollWidth:myDiv.get(0).scrollHeight;

			var delta=contentSize-containerSize;

			if(delta<1) return false;

			//check the positioning property
			if(myDiv.css("position")=="static") myDiv.css("position","relative");

			//handling the mouseWheel
			myDiv.mousewheel(function(event, delta){
				event.preventDefault();

				if(delta<0){
					if(horiz){
						scroller(myDiv).scrollRight(0.5);
					}else{
						scroller(myDiv).scrollUp(0.5);
					}
				}else{
					if(horiz){
						scroller(myDiv).scrollLeft(0.5);
					}else{
						scroller(myDiv).scrollDown(0.5);
					}
				}

				return false;
			});

			var myScrollBar=$("<div></div>")
			.addClass(options.className)
			.append(
					$("<a href='#left'></a>")
					.addClass(horiz?"left":"top")
					.click(function(ev){
						ev.preventDefault();
						if(horiz){
							scroller(myDiv).scrollLeft();
						}else{
							scroller(myDiv).scrollDown();
						}
						return false;
					})
					.css({
						float:horiz?"left":"none",
								display:"block",
								"min-width":10,
								height:"100%",
								"background-color":"#999"
					})
			)
			.append(
					$("<a href='#right'></a>")
					.addClass(horiz?"right":"bottom")
					.click(function(ev){
						ev.preventDefault();
						if(horiz){
							scroller(myDiv).scrollRight();
						}else{
							scroller(myDiv).scrollUp();
						}
						return false;
					})
					.css({float:horiz?"right":"none",display:"block","min-width":10,height:"100%","background-color":"#999"})
			)
			.append(
					$("<div class='bar'></div>")
					.css({
						position:"relative",
						height:"100%",
						overflow:"hidden"
					})
					.append(
							$("<div></div>")
							.addClass(horiz?"barLeftEnd":"barTopEnd")
							.css({float:horiz?"left":"none",display:"block"})
					)
					.append(
							$("<div></div>")
							.addClass(horiz?"barRightEnd":"barBottomEnd")
							.css({float:horiz?"right":"none",display:"block"})
					)
					.append(
							$("<a class='cursor'></a>")
							.mousedown(function(ev){
								var $this=$(this);

								moving=true;

								clickPos.left=ev.pageX;
								clickPos.top=ev.pageY;
								clickPos.cursorLeft=$this.position().left;
								clickPos.cursorTop=$this.position().top;


								$(document).bind("mousemove",{target:$this,clickPos:clickPos,horizontal:options.horizontal},_scrollBarMousemove);
								$(document).bind("mouseup",_scrollBarMouseUp);

							})
							.css({display:"block",position:"absolute",left:0,top:0,width:containerSize/contentSize*100 + "%",height:"100%","background-color":"#069"})
							.append(
									$("<span></span>")
									.addClass(horiz?"cursorLeftEnd":"cursorTopEnd")
									.css({float:horiz?"left":"none",display:"block"})
							)
							.append(
									$("<span></span>")
									.addClass(horiz?"cursorRightEnd":"cursorBottomEnd")
									.css({float:horiz?"right":"none",display:"block"})
							)
							.append(
									$("<span class='cursorBody'></span>")
									.css({display:"block"})
							)
					)
			)
			.css({
				"min-height":10,
				width:"100%",
				"background-color":"#eee",
				overflow:"hidden"
			});

			//finalizing the vertical style
			if(!horiz){
				myScrollBar.css({
					width:"auto",height:containerSize,position:"relative"
				});
				myScrollBar.children("a.top").css({position:"absolute",top:"0px","min-height":"10px",width:"100%",height:"auto"});
				myScrollBar.children("a.bottom").css({position:"absolute",bottom:"0px","min-height":"10px",width:"100%",height:"auto"});
				myScrollBar.find("div.barBottomEnd").css({position:"absolute",bottom:0,left:0});

				var cBottom=myScrollBar.find("span.cursorBottomEnd").css({
					position:"absolute",bottom:0,left:0
				});

				height = containerSize/contentSize*100;
				if (height<15) {
					height = 15;
				}

				var cur=myScrollBar.find("a.cursor").css({
					width:"100%",height:height + "%"
				});

			}

			// attach the scrollBar to the Dom
			if (options.barContainer){
				myScrollBar.appendTo(options.barContainer);
			}else{
				myScrollBar.insertAfter(myDiv);
			}


			//rechecking the bar size and position after the user css has been applyed
			if(!horiz){
				var top=myScrollBar.children("a.top").outerHeight(),
				bottom=myScrollBar.children("a.bottom").outerHeight(),
				len=myScrollBar.innerHeight()-top-bottom;

				myScrollBar.children("div.bar").css({position:"absolute",top:top,width:"100%",height:len});

				myScrollBar.find("span.cursorBody").css({
					height:cur.innerHeight()-myScrollBar.find("span.cursorTopEnd").outerHeight()-cBottom.outerHeight()
				});
			}

			//setting the event handler
			myDiv.scroll(function(){
				if (!moving){
					if (horiz){
						myScrollBar.find(".cursor").css("left",(myDiv.scrollLeft()/contentSize*100 + "%"));
					}else{
						myScrollBar.find(".cursor").css("top",(myDiv.scrollTop()/contentSize*100 + "%"));
					}

				}
			});

			//event function
			function _scrollBarMousemove(ev){

				var clickPos=ev.data.clickPos,
				horiz=ev.data.horizontal;

				var $this=ev.data.target,
				newPos=horiz?(ev.pageX-clickPos.left)+clickPos.cursorLeft:(ev.pageY-clickPos.top)+clickPos.cursorTop,
						cursor=myScrollBar.find(".cursor"),
						bar=myScrollBar.find(".bar");

				var barSize=horiz?bar.innerWidth():bar.innerHeight(),
						cursorSize=horiz?$this.outerWidth():$this.outerHeight(),


								newPos=(newPos<0)?0:newPos;
						newPos=(newPos+cursorSize<barSize)?newPos:barSize-cursorSize;

						$this.css(horiz?"left":"top",newPos);

						if (horiz){
							myDiv.scrollLeft(newPos*(contentSize-containerSize)/(barSize-cursorSize));
						}else{
							myDiv.scrollTop(newPos*(contentSize-containerSize)/(barSize-cursorSize));
						}
			}

			function _scrollBarMouseUp(ev){
				moving=false;
				$(document).unbind("mousemove",_scrollBarMousemove);
				$(document).unbind("mouseup",_scrollBarMouseUp);

				//needed to avoid selecting text!
				if(window.getSelection){
					var selection = window.getSelection();
					selection.collapse (selection.anchorNode, selection.anchorOffset);
				}
			}

		if ( window.location.hash ) {
			s_hash = window.location.hash.replace( 'ref_x', 'ref_' );
			colorbox_scroll_div = myDiv;
			colorbox_scroll_to = function( s_hash ) {
				try{colorbox_scroll_div.scrollTo( s_hash, 0);} catch(e) {}
			};
			colorbox_scroll_to( s_hash );
		}
}

/* ---------------------------------- */

function initializeFaqToggles(){
	var $=jQuery;
	
	$('dl.faqs dd').hide();
	$('dl.faqs dt').each(function(){
		$(this).html( '<a href="#">' + $(this).html() + '</a>' );
	});

	$('dl.faqs dt').click(function(){
		oDd = $(this).next();
		if (oDd.is(":visible")){
			oDd.hide();
		}
		else{
			oDd.show();
		}
		return false;
	});

	$('.categories').hide();
	$('.category-1').show();
	$('.faq-page #left-column .faq-categories li a').each(function(){
		sThisHref = $(this)[0].getAttribute('href', 2);
		if (sThisHref=='#category-1'){
			$(this).html('-- ' + $(this).html() + ' --');
		}
	});

	$('.faq-page #left-column .faq-categories li a').click(function(){
		$('.faq-page #left-column .faq-categories li a').each(function(){
			sLinkTitle = $(this).html();
			sLinkTitle = sLinkTitle.replace('-- ', '');
			sLinkTitle = sLinkTitle.replace(' --', '');
			$(this).html( sLinkTitle );
		});
		$(this).html( '-- ' + $(this).html() + ' --' );
		sTargetDiv = $(this)[0].getAttribute('href', 2);
		sTargetDiv = sTargetDiv.replace( '#', '.' );
		$('.categories').hide();
		$(sTargetDiv).show();
	});
}

function initialize$UiStuff($elt){
    var $=jQuery;
    if (!$elt) $elt = $(document);

    /* Homepage Tabs */
    if ( $(".home .tabContainer").length ){
        // ** JIRA GS-1049: Need to add the scrollbars before triggering jQuery's tab plugin
        $(".tabBody .carousel-outer").each(function(index,item){
            var myDiv=$(item);
            var params={
                horizontal:true,
                elemToScroll:myDiv,
                className:"myHorScrollBar",
                barContainer:null//myDiv.siblings(".horBar") //if null then scrollBar html will be inserted after the elemToScroll element.
            };


            /* Adding the horizontal scrollBar.
             *
             * JIRA GS-1049: Still attempting to add the scrollbars here even though the show event of
             * the jQuery tab plugin will recreate them because the left rounded end of the scrollbar
             * may not render properly with just the create logic in the show event functioning. Also,
             * in Internet Explorer a line may also appear under the tab labels if the calls below are
             * not made.
             */
            if ($.browser.webkit){
                $(window).load(function(){
                    addScrollBar(params);
                });
            }else{
                addScrollBar(params);
            }
        });

        $elt.find(".tabContainer").tabs({
            show: function(event, ui) {
                /* Initiated by JIRA GS-1049. */
                // ui.tab   - anchor element of the selected (clicked) tab
                // ui.panel - element, that contains the selected/clicked tab contents
                // ui.index - zero-based index of the selected (clicked) tab
                try {
                	if($.browser.webkit && ui.index < 1) {
                        /* Do not try to fix the visible tab's scrollbar because it would have been rendered properly
                         * for Safari or Chrome in the page onload event to prevent any intermittent appearance of
                         * a double scrollbar in Safari on the first tab.
                         */
                        return;
                    }

                    var CLS_CHROME_SAFARI_HZSCROLL_FIX = "chrome-safari-hzscroll-fix-done" /* When the scrollbar is marked with this class it is not recreated. */;

                    var markedScrollBar = $(ui.panel).find("."+CLS_CHROME_SAFARI_HZSCROLL_FIX);

                    if(markedScrollBar.length == 0) {
                        /* (JIRA GS-1049) Especially for Chrome and Safari: Recreate the scrollbar because the hidden ones
                         * were not created properly.
                         */
                        var currentScrollBar = $(ui.panel).find(".myHorScrollBar");
                        if(currentScrollBar.length > 0) {
                            // ** Remove the current scrollbar because it may not be showing nor rendering properly
                            currentScrollBar.remove();
                        }

                        var myDiv=$(ui.panel).find(".carousel-outer");

                        var params={
                            horizontal:true,
                            elemToScroll:myDiv,
                            className:"myHorScrollBar",
                            barContainer:null//myDiv.siblings(".horBar") //if null then scrollBar html will be inserted after the elemToScroll element.
                        };

                        addScrollBar(params);

                        // ** Mark the scrollbar so that its not recreated next time
                        $(ui.panel).find(".myHorScrollBar").addClass(CLS_CHROME_SAFARI_HZSCROLL_FIX);
                    }
                } catch(ex) {
                    alert(ex);
                }
            }
        });

//        $(".tabContainer ul.tabs li a").click(function () {
//        	var htmlBodyTop = $(window).scrollTop();
//        	window.location.hash = $(this).attr('href');
//        	$(window).scrollTop(htmlBodyTop);
//        });
//
//        if(!window.location.hash) {
//			$(window).load(function(){
//	        	window.location.hash = '#tab-1';
//	        	$(window).scrollTop(0);
//			});
//        }
    }

	// "accordions" - each headers container shown/hidden by it's own header only. All collapsed by default.
	$('.accordionContainer h3, .expandlist dt').next().hide();
	$('.accordionContainer h3, .expandlist dt').click( function(e){
		if( $(this).next().is(':visible') ) {
			$(this).next().hide();
			$(this).removeClass('ui-state-active');
		}
		else {
			$(this).next().show();
			$(this).addClass('ui-state-active');
		}
	});
}

try{
	$(window).load(function(){
		/* Carousels */
		// show the carousels //
		$('#carousel-1, #carousel-2, #carousel-3, #carousel-4, #carousel-5, #carousel-6, #carousel-7, #carousel-8, #carousel-9, #carousel-10').show();

		// build the carousels //
		$('.carouselContent, #carousel-1, #carousel-2, #carousel-3, #carousel-4, #carousel-5, #carousel-6, #carousel-7, #carousel-8, #carousel-9, #carousel-10, div.carousel-outer-box>ul').ixCarousel({
			pageOffset:3
		});

		/* autoScroller */
		$(".autoCarouselContent").ixCarousel({
			scrollDuration:1600,		//the scrolling duration in ms.
			autoStart:true,
			showButtons:false,
			showPag:false,
			slideDuration:8000
		});
	});
}catch(e){}

function initializeProductTabs(){
	var $=jQuery;
	var $tabs = $('ul.tabs');

	//remove bad DIV caused by include
	$('ul.tabs > div > li').each(function(){
		$(this).remove().appendTo($tabs);
	});

	$('ul.tabs > div').remove();
	var $tabBodies = $('<div id="tabBodies"></div>').insertAfter($tabs);
	$tabs.addClass('jsTabs')
	.find('h2')
	.each(function(){
		$(this).siblings('div')
		.hide()
		.remove()
		.appendTo($tabBodies);

		$(this).find('a').click(function(){
			$('.jsTabs li').removeClass('hit');
			$(this).closest('li').addClass('hit').get(0).blur();
			$('.tabBody').hide();
			var href = $(this).attr('href');
			var $target = $('div#'+href);
			$target.addClass('tabBody').show();
            $.cookie('activeTab', href); //GS-1249
			return false;
		});
	});
    //GS-1249 - try to remember the last active tab
    var activeTab = $tabs.find('h2:first a');
    var lastActiveTabValue = $.cookie('activeTab');
    if (lastActiveTabValue) {
        var links = $tabs.find('a[href=\'' + lastActiveTabValue + '\']');
        if (links.length > 0) {
            activeTab = $(links.get(0));
        }
        else {
            $.cookie('activeTab', null);
        }
    }
	activeTab.click();
}

function handleSearchResultsTypeFiltering(){
	
	var $=jQuery;
	
	var $resultDivs = $('#right-column div[id$=BooksResults]');
	var params = getUrlParameters();

	$resultDivs.hide();
	var tf = params['typeFilter'];
	if (!tf) tf = "all";
	$('#'+tf+'BooksResults').show();

	// hide sort by select after it has been restyled with ixdropdown
	$('.sortby-form select').hide();


	$('#content.search-page #left-column dl.left-navigation.last dd a').bind('click', function(){
		this.blur();
		var section = (this.id).split("-link")[0];
		var target = section + "BooksResults";
		$.scrollTo('#content');
		$resultDivs.hide();
		$('#'+target).show();
		return false;
	});
}

function mycarousel_initCallback(carousel){
	// Disable autoscrolling if the user clicks the prev or next button.
	carousel.buttonNext.bind('click', function(){
		carousel.startAuto(0);
	});

	carousel.buttonPrev.bind('click', function(){
		carousel.startAuto(0);
	});

	// Pause autoscrolling if the user moves with the cursor over the clip.
	carousel.clip.hover(function(){
		carousel.stopAuto();
	}, function(){
		carousel.startAuto();
	});
};


function setupSearchFormBehaviour(){
	var $=jQuery;
	$('.clear-on-focus')
		.each(
			function(){
				// put title attribute into field
				var actualValue = $(this).val();
				if (actualValue && actualValue != SEARCH_BOX_DEFAULT_TEXT){
					$(this).attr('focused', true);
					$(this).removeClass('clear-on-focus').addClass('typed-in');
				}else{
					$(this).val($(this).attr('title'));
				}
			}
		).focus(// The function .live('focus', does not work for jQuery 1.3.2 used by layout_legacy.xhtml
			function(e){
				var $=jQuery;
				var $target = $(e.target);
		        $target.attr('focused', true);
				if ($target.hasClass('typed-in')){
					return;
				}else{
		            $(e.target).addClass('typed-in');
					$target.val('');
				}
			}
		).blur(// The function .live('blur', does not work for jQuery 1.3.2 used by layout_legacy.xhtml
			function(e){
				var $target = $(e.target);
				if ($target.hasClass('typed-in')) return;
				$target.removeClass('enlarged');
				// put title text back
				$target.val($target.attr('title'));
			}
		).live('keypress', 
			function(e){ // sadly, this also catches the tab key
				// change colour, prevent default text being put back
				// NOTE: if catching tab is a problem, event.which can be checked to determine which key is pressed.
				$(e.target).addClass('typed-in');
			}
		);

	$('#catalogue-picker-set input').live('click', function(){
		adjustSubjectPickerAvailability();
	});

	adjustSubjectPickerAvailability(); // could differ from default if user refreshes page after checking a radio button
}

function clearEmptyFields(elt){ // currently called from search ribbon submit button's onclick
	if (!elt) elt = document;
	$(elt).closest('form').find('.clear-on-focus').each(function(){
		if (!$(this).hasClass('typed-in') ||$(this).val() == SEARCH_BOX_DEFAULT_TEXT){
			$(this).val('');
		}
	});
}

/**
 * Returns a jquery wrapped element which has the given html id, as generated by faces. If the element is not found,
 * and exception is thrown.
 *
 * @param facesHtmlId the id of an html element, as generated by Faces.
 */
function getJQueryElement(facesHtmlId) {
    var element = $("#" + facesHtmlId.replace(":", "\\:"));
    if (element.size() == 0) {
      throw "Field with id " + facesHtmlId + " not found";
    }
    else {
        return element;
    }
}

/**
 * Checks if any value has been entered in a search field
 * @param searchInputFieldHtmlId the id of an HTML input text
 */
function isSearchEmpty(searchInputFieldHtmlId) {
    var searchInputField = getJQueryElement(searchInputFieldHtmlId);
    // remove leading/trailing whitespace
    var searchInputFieldValue = searchInputField.val().replace(/^\s+|\s+$/g, "");
    return searchInputFieldValue.length == 0 || !searchInputField.attr('focused');
}

/**
 * Validates prior to a search, that search terms have been entered. If not, an error message is raised.
 * @param searchInputFieldHtmlId
 * @param errorMessage
 */
function validateSearchInput(searchInputFieldHtmlId, errorMessage) {
    if (isSearchEmpty(searchInputFieldHtmlId)) {
        alert((errorMessage == undefined || errorMessage == null) ? "Please enter keyword(s) or search term and try again." : errorMessage);
        return false;
    }
    return true;
}

/**
 * Performs a search validation and if successful, clears the search fields.
 * @param element
 * @param searchInputFieldHtmlId
 */
function validateSearchAndClearFields(element, searchInputFieldHtmlId) {
    var searchValidated = validateSearchInput(searchInputFieldHtmlId, null);
    if (searchValidated) {
        clearEmptyFields(element);
    }
    return searchValidated;
}

function adjustSubjectPickerAvailability(){
	var $=jQuery;
	var $subjectDropdown = $('#subject-picker-set a.ixDropDown_A');
	var $clicker = $subjectDropdown.find('.jqTransformSelectOpen');
	var allIsActive = $('#catalogue-picker-set input[value=all]').attr('checked'); // boolean

	$subjectDropdown.disabled(allIsActive);
}

function getUrlParameters(){
	var map = {};
	var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,   function(m,key,value){
		map[key] = value;
	});
	return map;
}

function reloadPageWithSelectedCountry(url, queryString){
	var country = $("#region").val();
	queryString = setUrlEncodedKey('region', country, queryString);

	url += queryString;
	window.location = url;
}

getUrlEncodedKey = function(key, query){
	if (!query)
		query = window.location.search;
	var re = new RegExp("[?|&]" + key + "=(.*?)&");
	var matches = re.exec(query + "&");
	if (!matches || matches.length < 2)
		return "";
	return decodeURIComponent(matches[1].replace("+", " "));
};

setUrlEncodedKey = function(key, value, query){
	query = query || window.location.search;
	var q = "";

	if (query.length > 0) {
		q = query + "&";

		var re = new RegExp("[?&]?" + key + "=[^&]*&?");
		if (re.test(q)) {
			q = q.replace(re, "&" + key + "=" + encodeURIComponent(value) + "&");
		}
		else {
			q += (key + "=" + encodeURI(value));
		}

		q = q.trimStart("&").trimEnd("&");
		if (q[0] != "?") {
			q = "?" + q;
		}
	}
	else {
		q = "?" + key + "=" + encodeURI(value);
	}

	return q;
};

String.prototype.trimEnd = function(c){
	if (c)
		return this.replace(new RegExp(c.escapeRegExp() + "*$"), '');
	return this.replace(/\s+$/, '');
};
String.prototype.trimStart = function(c){
	if (c)
		return this.replace(new RegExp("^" + c.escapeRegExp() + "*"), '');
	return this.replace(/^\s+/, '');
};

String.prototype.escapeRegExp = function(){
	return this.replace(/[.*+?^${}()|[\]\/\\]/g, "\\$0");
};

////////////////
// ixCarousel //
////////////////
(function($){
	$.fn.ixCarousel=function(options){
		var defaults={
			onScroll:function(){},
			className:"",
			scrollDuration:600,
			scrollSize:1,
			pageOffset:0,		//used when the items to scroll have a margin you need to complensate
			showButtons:true,
			showPag:true,
			autoStart:false,
			slideDuration:5000
		};

		$.extend(defaults,options);
		
		function doSlide(defaults){
			var $this=$(this);

			if ($this.scrollLeft()==this.scrollWidth-$this.innerWidth()){
				$this.animate({scrollLeft:0},defaults.scrollDuration);
			}else{
				scroller(this).scrollRight(defaults.scrollSize,defaults.scrollDuration);
			}
		}

        return this.each(function(){
			var timerHnd=null;
			var carousel=$(this);

			carousel.addClass("carouselContainer");

			if (!carousel.parent("div").hasClass("ixCarousel")){
				// Wrap with <div>
				carousel.wrap($("<div class='ixCarousel'></div>").addClass(defaults.className));

				carousel.scroll(function(ev){
					var carouselScroll=$(this);

					if (carouselScroll.scrollLeft()==0){
						carouselScroll.siblings("a.left").addClass("off");
					}else{
						carouselScroll.siblings("a.left").removeClass("off");
					}					
					
					if (carouselScroll.scrollLeft()==this.scrollWidth-carouselScroll.innerWidth()){
						carouselScroll.siblings("a.right").addClass("off");
					}else{
						carouselScroll.siblings("a.right").removeClass("off");
					}

					if(defaults.showPag){
						//checking the pagination
						var pagination=carouselScroll.siblings("div.paginationContainer");
						var li=pagination.find("li");
						var curPage=Math.ceil(carouselScroll.scrollLeft()/(carouselScroll.innerWidth()+defaults.pageOffset));
						var curLi=li.eq(curPage);

						if(!curLi.hasClass("selected")){
							li.removeClass("selected");
							curLi.addClass("selected");
						}
					}

					//event callBack
					defaults.onScroll.call(this, ev);
				});
				
				if (defaults.showButtons){
					// left arrow button
					$("<a href='#left' class='left'></a>")
						.focus(function(){$(this).addClass("focus");})
						.blur(function(){$(this).removeClass("focus");})
						.mouseup(function(){$(this).removeClass("focus");})
						.click(function(){
							if (timerHnd) clearInterval(timerHnd);
							
							scroller(carousel).scrollLeft(defaults.scrollSize,defaults.scrollDuration,true,true);
							return false;
						})		
						.insertBefore(carousel);

					// right arrow button
					$("<a href='#right' class='right'></a>")
						.focus(function(){$(this).addClass("focus");})
						.blur(function(){$(this).removeClass("focus");})
						.mouseup(function(){$(this).removeClass("focus");})
						.click(function(){
							if (timerHnd) clearInterval(timerHnd);
							
							scroller(carousel).scrollRight(defaults.scrollSize,defaults.scrollDuration,true,true);
							return false;
						})
						.insertAfter(carousel);
				}

				if(defaults.showPag){
					var carousel = $(this);
					var carouselItemCnt = carousel.find("li").length;

					if (carouselItemCnt > 0){
						//creating the pagination code
						var pagDiv = $("<div class='paginationContainer'></div>").insertAfter(carousel);
						var ul = $("<ul></ul>").appendTo(pagDiv);
						var pageCount = Math.ceil((this.scrollWidth-defaults.pageOffset)/carousel.innerWidth());
						
						//make sure that we don't have more pages than we do books.
						pageCount = Math.min(pageCount, carouselItemCnt);
		                
						for(var x=0; x<pageCount; ++x){
							$("<a></a>")
								.focus(function(){$(this).addClass("focus");})
								.blur(function(){$(this).removeClass("focus");})
								.mouseup(function(){$(this).removeClass("focus");})
								.attr("href","#"+x)
								.data("index",x)
								.click(function(){
		                            var $this=$(this);
		                            var ul=$this.closest("div").siblings("ul").stop();
		                            var curPage=$this.closest("div").find("li.selected a").data("index");
		                            var thisPage=$this.data("index");
		                            var jumpSize=curPage-thisPage;
									
									if(defaults.autoStart){
										clearInterval(carousel.data("timerHnd"));
									}
									
									if (jumpSize==0){
										return false;
									}
									
									if (jumpSize<0){
										scroller(ul).scrollRight(Math.abs(jumpSize),defaults.duration);
									}else{
										scroller(ul).scrollLeft(Math.abs(jumpSize),defaults.duration);
									}

									return false;
								})
								.append($("<span/>").text(x+1))
								.appendTo($("<li></li>").appendTo(ul));
						}
					}

					carousel.scroll();
				}

				if(defaults.autoStart){
					timerHnd=setInterval(function(){doSlide.call(carousel.get(0),defaults);},defaults.slideDuration);
					carousel.data("timerHnd",timerHnd);
				}
			}
        });
	};
})(jQuery);

function buttonSwap( strState, strColor )
{
    var buttons = document.getElementById('SearchButton');
    if ( buttons != null )
    {
		if ( strState=='over' ) {
			buttons.src="/_res/images/static/search_" + strColor + "_over.png";
		}
		else {
			buttons.src="/_res/images/static/search_" + strColor + ".png";
		}
    }
}

function initializeColorbox() 
{
    var $=jQuery;
	if ($().colorbox) 
	{
		// colorbox plugin used to display overlay - opens new html page into div
		$('a.modalOverlay').colorbox({
			onComplete:function(box) 
			{
				//applying the custom scrollBar to the popup content
				box.find("div.verScroll, #contact-us-popup-inner").each(function(index,item) {
						var myDiv=$(item);
						addScrollBar({
							horizontal:false,
							elemToScroll:myDiv,
							className:"verScrollBar overlayScroll"/*,
							barContainer:null				//if null then scrollBar html will be inserted after the elemToScroll element.*/
						});
					});
				if ($(this).attr('anchor')) {
					window.location.hash = "#" +  $(this).attr('anchor');
				}
		   }, 
			href:function() 
			{
				if ($(this).attr('anchor')) {
					window.location.hash = "#" +  $(this).attr('anchor');
				}
	      	
				var url = this.href;
				var anchorIndex = url.indexOf("#");
				if (anchorIndex != -1) {
					var anchor = url.substring(anchorIndex + 1);
					$(this).attr('anchor', anchor);
					if ( colorbox_scroll_to ) {
						s_hash = '#' + anchor.replace( 'ref_x', 'ref_' );
						colorbox_scroll_to( s_hash );
					}
					return url.substring(0, anchorIndex);
				}
				else {
					return url;
				}
			}
		});
	}
}

/* Copyright (c) 2006 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * 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.
 *
 * $LastChangedDate: 2007-12-20 09:02:08 -0600 (Thu, 20 Dec 2007) $
 * $Rev: 4265 $
 *
 * Version: 3.0
 *
 * Requires: $ 1.2.2+
 */
(function($){
	$.event.special.mousewheel = {
			setup: function(){
				var handler = $.event.special.mousewheel.handler;

				// Fix pageX, pageY, clientX and clientY for mozilla
				if ( $.browser.mozilla )
					$(this).bind('mousemove.mousewheel', function(event){
						$.data(this, 'mwcursorposdata', {
							pageX: event.pageX,
							pageY: event.pageY,
							clientX: event.clientX,
							clientY: event.clientY
						});
					});

				if ( this.addEventListener )
					this.addEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false);
				else
					this.onmousewheel = handler;
			},

			teardown: function(){
				var handler = $.event.special.mousewheel.handler;

				$(this).unbind('mousemove.mousewheel');

				if ( this.removeEventListener )
					this.removeEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false);
				else
					this.onmousewheel = function(){};

					$.removeData(this, 'mwcursorposdata');
			},

			handler: function(event){
				var args = Array.prototype.slice.call( arguments, 1 );

				event = $.event.fix(event || window.event);
				// Get correct pageX, pageY, clientX and clientY for mozilla
				$.extend( event, $.data(this, 'mwcursorposdata') || {});
				var delta = 0, returnValue = true;

				if (event.wheelDelta) delta = event.wheelDelta/120;
				if (event.detail) delta = -event.detail/3;
//				if ($.browser.opera) delta = -event.wheelDelta;

				event.data = event.data || {};
				event.type = "mousewheel";

				// Add delta to the front of the arguments
				args.unshift(delta);
				// Add event to the front of the arguments
				args.unshift(event);

				return $.event.handle.apply(this, args);
			}
	};

	$.fn.extend({
		mousewheel: function(fn){
			return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
		},

		unmousewheel: function(fn){
			return this.unbind("mousewheel", fn);
		}
	});
})(jQuery);
