// AIS
/*
	use minify to reduce filesize of published ais.js

	requires: jquery-1.3.2.min.js
	no longer requires: jquery.cookie.min.js
	
	naming conventions:
		camelCaseFunctions 
		CapitalisedCamelCaseConstructors  
		under_score_variables 
		hyphenated-css-classes-and-ids
		$jquery_objects start with a $ sigil
	
	beware! jQuery doesn't like to compete with window.onload used by other scripts
	
	
	
	test in ie7 add alerts to returns
*/
/*globals $, jQuery, ais */

// jQuery.noConflict();
var ais = ais || {};

(function ($) {
	
	ais.init = function () {

		if ($('#scWebEditRibbon').size() === 0) { // then you're not in sitecore edit mode
			ais.jsCSS();
			ais.url.hash.init();
			
			ais.prepMainNav(".nav-bar");
		
			ais.prepLinkRels("Opens in new window");
			ais.initSearch(".search-field");
			
			ais.prepQuotes(20000, 3000); //pause between fades, fade_speed
			
			ais.initAccordion(); // update?
			
			ais.switcher.init(); // style sheet & font size switcher
		
			ais.tabs.init();

			ais.preCache([
				'../chrome/angles/lines/angle_42x98_bbe5fa_line.png',
				'../chrome/angles/lines/angle_42x98_009bc9_line.png',
				'../chrome/angles/angle_009bc9_84x98.png',
				'../chrome/angles/angle_fff_84x98.png',
				'../chrome/angles/angle_003e7e_84x98.png'			
			]);
		
		} else {
			$("#wrapper").addClass('webedit');
		}
	};

	ais.initSearch = function (search_selector_str) {
		$(search_selector_str)
		    .each(function () {
			    var search_field_text, $submit_btn; //$search_field = $(this)
			
			    //search_field_text = $(this).val();
			    search_field_text = $(this).attr("title"); /* fixes f5 refresh ff3 bug */
			    $(this)
				    .focus(function () {
					    if (this.value === search_field_text) {
						    this.value = '';
						    $(this).addClass("focussed");
					    }
				    })
				    .blur(function () { 
					    if (this.value === "") {
						    this.value = search_field_text;
						    $(this).removeClass("focussed");
					    }
				    });
				
	// $submit_btn = $(this).nextAll("input[type='submit']:first"); //.get(0); 
	//$submit_btn = $(this).next("input[type='submit']:first"); 
	//$(this).keypress(function (e) {
	//if (e.which && e.which === 13) { // || (e.keyCode && e.keyCode === 13)) {
	//$submit_btn.click();
	//}; 
	//});
									 
		});	
	};
	
	ais.jsCSS = function () { 
		// enable javascript dependent css
		$('body').addClass('js');
	};
	
	ais.prepLinkRels = function (message) {
		// fix _blank rel=external
		message = message || "(Opens in new window)";
		
		$("a[rel*='external']")
			.click(function () {
				window.open($(this).attr('href'));
				return false;
			})
			.each(function () {
				var title = $(this).attr("title");
				if (!title) {
					$(this).attr("title", message);
					// this.setAttribute("title", message);
				}
			});
	};
	
	ais.cookie = { // cookie functions copied from code by Peter Paul Koch : http://www.quirksmode.org
		set : function (name, value, days) { 
			var date, expires;
			if (days) {
				date = new Date();
				date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
				expires = "; expires=" + date.toGMTString();
			} else {
				expires = "";
			}
			document.cookie = name + "=" + value + expires + "; path=/";
		},
		get : function (name) {
			var nameEq, cookie_array, i, i_cookie;
			nameEq = name + "=";
			cookie_array = document.cookie.split(';');
			for (i = 0; i < cookie_array.length; i++) {
				i_cookie = cookie_array[i];
				while (i_cookie.charAt(0) === ' ') {
					i_cookie = i_cookie.substring(1, i_cookie.length);
				}
				if (i_cookie.indexOf(nameEq) === 0) {
					return i_cookie.substring(nameEq.length, i_cookie.length);
				}
			}
			return null;
		},
		del : function (name) {
			ais.cookie.set(name, "", -1);
		}
	};
	
	// ed
	//for(var i = 0; i < 6; i++){
	//var target = temp.get(i);
	//var div = document.createElement('div');
	//div.className = "this";
	//div.appendChild(target.cloneNode(true));
	//target.replaceNode(div);
	//};
	////temp.wrap('<div class="this"></div>');
	//debugger;
	
	
	ais.prepMainNav = function (selector_str) {
	    
	    $('a:not(.this)', selector_str)
			.hover(
				function () {
					$(this)
						.parent()
						.parent()
						.not('.this')
						.addClass('hover');
				}, 
				function () {
					$(this)
						.parent()
						.parent()
						.removeClass('hover');
				});
				
	/*
		$('span, a.this', selector_str)
			.wrap('<div class="this"></div>')
			.wrap('<div></div>');
		$('a:not(.this)', selector_str)
			.wrap('<div></div>')
			.wrap('<div></div>')
			.hover(
				function () {
					$(this)
						.parent()
						.parent()
						.addClass('hover');
				}, 
				function () {
					$(this)
						.parent()
						.parent()
						.removeClass('hover');
				});
			
		$(selector_str)
			.each(function () {
				$(this)
					.children(':first')
					.addClass('first');
					//.filter('.this')
					//.addClass('this-first')
					//.removeClass('first')
			});
	*/
	};
	
	ais.prepQuotes = function (pause, fade_speed) {
		var quoteGroupClosure;
		
		quoteGroupClosure = function ($group, number_of_quotes, quote_width) {
			var current_quote, timeout, timeoutQuoteFunction;
			current_quote = 0;
			
			timeoutQuoteFunction = function () {
				var position;
				
				//fadeout current quote
				$group.fadeOut(fade_speed, function () {
					
					//update current index, reset if too large
					current_quote++;
					if (current_quote >= number_of_quotes) {
						current_quote = 0;
					}
					
					position = 0 - (current_quote * quote_width);
					
					// move group to show new (current) quote
					$group.get(0).style.left = position + "px";
					
					// and fade it in
					$group.fadeIn(fade_speed);
				});
				
				clearTimeout(timeout);
				timeout = setTimeout(timeoutQuoteFunction, pause);
			};
			timeout = setTimeout(timeoutQuoteFunction, pause); // set first timeout
		};
		
		$('.quotes-box')
			.each(function () {
				// this function could act as the closure instead, despite .each feeling like a loop
				var $quotes_group, $quotes, quote_width, group_width_str, number_of_quotes;
			
				$quotes_group = $('.quotes-group', this); // should only be one although $ is a group (of one)
				$quotes = $('.quote', $quotes_group);
				number_of_quotes = $quotes.length;
			
				// set width of quotes frame
				quote_width = $quotes.get(0).offsetWidth;
				group_width_str = (quote_width * number_of_quotes) + "px";
				$quotes_group.get(0).style.width = group_width_str;
				
				// make sure group is positioned correctly
				if (!$quotes_group.get(0).style.left) {
					$quotes_group.get(0).style.left = "0px";
				}
				
				quoteGroupClosure($quotes_group, number_of_quotes, quote_width);
		});
	};
		
	ais.initAccordion = function () {
		// requires: only one accordion per page
		
		var page_str = ais.prefs.text.page + " ";
		$('.accordion').each(function () {
		
			$('.leaf', this)
				.each(function (i) {
					var page_num, $leaf, $leaf_inner, $a, $span_open_close, $span_hover;
					page_num = i + 1;
					
					$leaf = $(this);
					$leaf
						.wrapInner('<div class="leaf-inner"></div>');
						
					$leaf_inner = $leaf
						.children('.leaf-inner')
						.eq(0)
						.hide();	
					
					$span_hover = $('<span></span>')
						.text(page_str + page_num);
						
					$span_open_close = $('<span></span>')
						.append($span_hover);
					
					$a = $('<a href="#"></a>');
					$a
						.addClass('leaf-toggle')
						.click(function () {
						
							if ($leaf_inner.is(':visible')) {
								$leaf
									.removeClass('leaf-open')
									.children('.leaf-inner')
									.slideUp('slow');		
							} else {
								$leaf
									.addClass('leaf-open')
									.children('.leaf-inner')
									.slideDown('slow')
									.end()
									.siblings()
									.removeClass('leaf-open')
									.filter(':visible')
									.children('.leaf-inner')
									.slideUp('slow');
							}
							$a.blur();
							return false;
						})
						.hover(
							function () {
								$span_hover.addClass("hover");
							}, 
							function () {
								$span_hover.removeClass("hover");
							})
						.append($span_open_close);
						
					$leaf.prepend($a);
				});
				
				// opens first leaf of each accordion , remove [this] if only first leaf of page is required to be open
				$('.leaf:first', this) 
					.addClass("leaf-open")
					.children('.leaf-inner')
					.show();
		});
	};
	
	
	
	
	ais.switcher = {
		test: function (arg) {
			alert('test: ' + arg);
		},
		init: function () {
			var initCssSwitching, initFontSwitching;
			
			// alert('switcher init');
			
			// check ifeither cookie exists:
			// if yes: switch to cookie choices (if possible, else use default) and signal choices
			// if no:
			// can cookies be used?
			// if no: abandon installation
			// if yes: set cookie with defaults (no need to switch, but make sure signals ok)
	
			initCssSwitching = function () {
				
				// make a list of useable css link tags
				var prefs, link_elements, titles, i, i_title, default_title, css_cookie_str, setStyleSheetLinks, attachClick, setStyleSheet, setCssCookie;
				
				setStyleSheetLinks = function (style_sheet_title) {
					// called by: initCssSwitching(), setStyleSheet()
					$("link[rel*='style'][title='" + style_sheet_title + "']")
						.each(function () { // only swap if style can be found
							$("link[rel*='style'][title][media='screen']")
								.each(function () {// disable all
									this.disabled = true;
								});
							this.disabled = false; // enable matching style sheet			
						});
				}; // eo: setLinks
				
				// closure for attaching event to node within loop
				attachClick = function ($node, title) {
					$node.click(function () {			
						setStyleSheet(title);
						//setCssCookie(title);
						$(this).blur();
						return false;
					});				
				};
				
				setCssCookie = function (style_sheet_title) {
					if (titles[style_sheet_title] === undefined) {
						alert('setCssCookie error: ' + style_sheet_title);
						return;
					}
					ais.cookie.set(prefs.cookie_name, style_sheet_title, prefs.cookie_expiry);
				};	
					
				setStyleSheet = function (style_sheet_title) {
					// argument matches <link title> and may be:
					// Default	
					// Enhanced Readability Style 
					// High Contrast Style
					
					if (titles[style_sheet_title] === undefined) {
						alert('setStyleSheet error: ' + css_cookie_str);
						return;
					}
					
					var i, i_abbr, i_node, i_title, i_label, i_class, i_action, i_selected, $options_selector, current_title, previous_css_class, new_css_class, er;
					
					// update style sheet
					setStyleSheetLinks(style_sheet_title);
					
					// if needed remove class from body
					// then add class to body
					current_title = ais.cookie.get(prefs.cookie_name);
					if (current_title) {
						previous_css_class = prefs.lookup[current_title].css_class;
						$("#wrapper").removeClass(previous_css_class);
					}
					new_css_class =prefs.lookup[style_sheet_title].css_class;
					$("#wrapper").addClass(new_css_class);
				
					// update signals
					$options_selector = $(prefs.options_selector); //.get(0);
					$options_selector.html('');
					
					for (i = 0; i < prefs.options.length; i++) {
						
						i_title = prefs.options[i].title;		// "Default",								// matches <link> CopyAdvice
						i_action = prefs.options[i].action;		// "view the page in the Default style",	// used in button <a><abbr> title
						i_selected = prefs.options[i].selected;
						i_label = prefs.options[i].label;		// "C",										// label text of button
						i_class = prefs.options[i].css_class;	// "default",
						
						if (i_title === style_sheet_title) {
							
							try	{ // ie6 !abbr
								i_abbr = $('<abbr></abbr>')
									.text(i_label)
									.attr({title: i_selected});
								}
							catch (er) {
								i_abbr = $('<span></span>')
									.text(i_label)
									.attr({title: i_selected});	
								}
								
							i_node = $('<span></span>')
								.addClass(i_class)
								.addClass('this')
								.append(i_abbr);
	
						} else {
							
							try { // ie6 !abbr
								i_abbr = $('<abbr></abbr>')
									.text(i_label)
									.attr({title: i_action});
								}
							catch (er) {
								i_abbr = $('<span></span>')
									.text(i_label)
									.attr({title: i_action});
								}
							
							i_node = $('<a></a>')
								.attr('href', '#')
								.addClass(i_class)
								.append(i_abbr);
							
							attachClick(i_node, i_title);	
						}
						$options_selector.append(i_node);
					}
					
					setCssCookie(style_sheet_title); // link has been tested to exist
					
					// remove previous class on body if there
					// add class to body
					//$('body').addClass('js'); // can't remember why? remove this???
					
				}; // eo: setStyleSheet
				
				
				// funcs are now defined, so now do stuff for initialising
				prefs = ais.prefs.css;
				
				// make look up hash from prefs
				prefs.lookup = {};
				for (i = 0; i < prefs.options.length; i++) {
					i_title = prefs.options[i].title;
					
					prefs.lookup[i_title] = {
						index : i,
						title : i_title,
						css_class : prefs.options[i].css_class
					};
				}
				
				link_elements = $('link[rel*=style][title][media=screen]'); // returns object
				if (!link_elements || (link_elements.length < 2)) {
					// no style sheets to switch between, so don't install switcher
					alert('373 link_elements ' + link_elements);
					return;
				}
				
				// make css link titles hash
				titles = {};
				for (i = 0; i < link_elements.length; i++) {
					i_title = link_elements[i].title;
					titles[i_title] = i;
				}
				
				// find the (first) css link that isn't an alternative, otherwise (something is wrong but) use an available (alt?) link
				default_title = $('link[rel*=style][title][media=screen]').not('[rel*=alt]')[0].title || i_title;
				
				// check if cookie exists
				css_cookie_str = ais.cookie.get(prefs.cookie_name);
				/*
				if (css_cookie_str) {
					if (titles[css_cookie_str] !== undefined) { // then cookie style available on this page
						// swap style to match cookie (if needed)
						setStyleSheet(css_cookie_str);	
					} else { // cookie exists but style unavailable, so use default style and update cookie
						// use default style, so no need to swap styles
						ais.cookie.set(prefs.cookie_name, default_title, prefs.cookie_expiry);
						setStyleSheet(css_cookie_str);	// abstract into just signal update?
					}
				} else { // no cookie! try to create one...
					// use default style, so no need to swap styles
					ais.cookie.set(prefs.cookie_name, default_title, prefs.cookie_expiry);
					
					css_cookie_str = ais.cookie.get(prefs.cookie_name);
					if (!css_cookie_str) { // cannot create cookie, cookies must be turned off, so don't install switcher
						
						alert('406 css_cookie_str ' + css_cookie_str);
						return;
					} else {
						setStyleSheet(css_cookie_str);
					}
				}
				*/
				if (css_cookie_str) {
					if (titles[css_cookie_str] === undefined) {
						// cookie exists, but there is no corresponding link title
						ais.cookie.set(prefs.cookie_name, default_title, prefs.cookie_expiry);
					}
				} else {
					// no cookie! try to create one...
					ais.cookie.set(prefs.cookie_name, default_title, prefs.cookie_expiry);
					css_cookie_str = ais.cookie.get(prefs.cookie_name);
					if (!css_cookie_str) { 
						// cannot create cookie so don't install switcher
						// alert('504 css_cookie_str ' + css_cookie_str);
						return;
					}
				}
				
				// by this point cookie must exist and have a corresponding link title, as does css_cookie_str
				// body will not have a style sheet class (when init called)
				setStyleSheet(css_cookie_str);	// abstract into just signal update?
				
				// switch style sheet functions
					// update style sheet
					// update buttons
			};
	
		
			initFontSwitching = function () {
				var i, prefs, font_cookie_str, font_cookie_num, setFontSize, setFontCookie, attachClick;
				
				// closure for attaching event to node within loop
				attachClick = function ($node, index) {
					$node.click(function () {
						setFontSize(index);
						setFontCookie(index);
						
						$(this).blur();
						return false;
					});				
				};
				
				setFontCookie = function (option_num) {
					// requires: a number as a string
					ais.cookie.set(prefs.cookie_name, String(option_num), prefs.cookie_expiry);
				};
	
				setFontSize = function (option_num) {
					// requires a number
					if (typeof option_num === String) {
						option_num = Number(option_num);
					}
					
					var font_size, $options_selector, i_size_num, i_label, i_action, i_selected, i_node, i_abbr;
					
					// set font size
					font_size = prefs.options[option_num].size + "%";
					$('body').css({fontSize: font_size});
					
					// signal font size
					$options_selector = $(prefs.options_selector); //.get(0);
					$options_selector.html('');
					
					for (i = 0; i < prefs.options.length; i++) {
						i_size_num = prefs.options[i].size;
						i_label = prefs.options[i].label;
						i_action = prefs.options[i].action; 
						i_selected = prefs.options[i].selected;
						
						if (i === option_num) {
						
							try {
									i_abbr = $('<abbr></abbr>')
										.text(i_label)
										.attr({title: i_selected});
								}
								catch (er) {
									i_abbr = $('<span></span>')
										.text(i_label)
										.attr({title: i_selected});
								}
							
							i_node = $('<span></span>')
								.addClass('font-size-' + i)
								.addClass('this')
								.append(i_abbr);
	
						} else {
							
							try {
									i_abbr = $('<abbr></abbr>')
										.text(i_label)
										.attr({title: i_action});
								}
								catch (er) {
							i_abbr = $('<span></span>')
								.text(i_label)
								.attr({title: i_action});
								}
							
							i_node = $('<a></a>')
								.attr('href', '#')
								.addClass('font-size-' + i)
								.append(i_abbr);
							
							attachClick(i_node, i);
							
						}
						$options_selector.append(i_node);
					}		
				}; // eo: setFontSize
				
				// vars
				prefs = ais.prefs.font;
				
				// check cookie exists, or could exist (and be set to default), and read it or leave function
				font_cookie_str = ais.cookie.get(prefs.cookie_name);
				if ((font_cookie_str === null) || (font_cookie_str === undefined)) { // value of cookie string can be 0 thus falsy
					// if no cookie, then create one set to default value
					ais.cookie.set(prefs.cookie_name, prefs.default_index, prefs.cookie_expiry);
					
					font_cookie_str = ais.cookie.get(prefs.cookie_name);
					if (!font_cookie_str) { // cannot create cookie, cookies must be turned off, so don't install switcher
						return;
					}
				}
				
				// if at this point then cookies may be set, 
				// either cookie has been read, or cookie set to default
				// and cookie_str is set
				
				font_cookie_num = Number(font_cookie_str);
				setFontSize(font_cookie_num); // cookie holds array index number		
			}; // eo: initFontSwitching
			
			initCssSwitching();
			initFontSwitching();	
		}
	};
						
							
							
							
	ais.prefs = {
		text : { // if multilingual required this could be written into head (with an english backup in .js)
			backtotop: "back to top", // not used
			page: "Page" // used by accordion
		},
		cookie_expires : 90,
		font : { // switcher
			options_selector: ".font-size-options", //jQuery
			default_index: 0,
			options: [
				{size: 100, px:13, action: "switch to normal font size", 	selected: "normal font size is displayed", 	label: "A"},
				{size: 123, px:16, action: "switch to larger font size", 	selected: "larger font size is displayed", 	label: "A"},
				{size: 140, px:18, action: "switch to largest font size", 	selected: "largest font size is displayed", label: "A"}
			],
			cookie_name: "copyadvice-font-size"
		},
		css : { // switcher
			options_selector: ".css-switcher-options", //jQuery
			options: [
				{
					title: "Default",								// matches <link> CopyAdvice
					action: "view the page in the Default style",	// used in button <a><abbr> title
					selected: "the Default page style is being used",	// used in span / .this <abbr> title
					label: "C",										// text of button
					css_class: "default", 							// css class to style button
					simple_flag: false								// activate simple mode, turn off js features / animations // optional
				},
				{
					title: "Enhanced Readability Style", 
					action: "view the page in an Enhanced Readability style",
					selected: "the Enhanced Readability style is being used",
					label: "C", 
					css_class: "enhanced"
				},
				{
					title: "High Contrast Style", 
					action: "view the page in a High Contrast style",
					selected: "the High Contrast style is being used",
					label: "C", 
					css_class: "high-contrast"
				}
			],
			cookie_name: "copyadvice-css"
		}
	};
	
	ais.prepScroller = function () {
	    $("a[href^='#']")
	        .click(function () {
	            var id, scroll_top;
	            id = $(this).attr('href');
	            scroll_top = $(id).offset().top;
	            $('html, body').animate({scrollTop:scroll_top}, 2000);
	            $(this).blur();
	            return false;
	        });
	};
	
	ais.cache = {};
	ais.preCache = function (img_name_array) {
		// cache images
		var i, cache, img_name; //, error;
		
		cache = ais.cache || {};
		// ais = ais ? ais : {};
		
		if (arguments.length === 0) {
			//error = new Error(); 
			//error.name = 'ais.preCache'; 
			//error.message = 'cannot pre cache';
			//throw(error);
			
			// alert('preCache');
			return false; 
		}
		
		for (i = 0; i < img_name_array.length; i++) {
			img_name = img_name_array[i];
				
			// only cache image if it is not already in cache
			if (!cache[img_name]) {
				cache[img_name] = new Image();
				cache[img_name].src = img_name;
			}

		}
		
		/*
		var s, str = ""
		for (s in ais.cache) {
		str = ais.cache[s].src + ' ';
		
		alert(str);
		}
		*/		
	};
	
	ais.url = {
		hash: {
			init: function () {
				this.str = decodeURI(location.hash.substring(1)); // substring(1) removes first ? character
			},
			str: ""
		}
	};
	
	ais.tabs = {
		// v3.5.5
		/*

		requires: 
			ais.jsCSS, ais.url.hash
			OSX Safari 4 needs css to be written before js in the head to avoid incorrect offsetWidth

		assumes:
			.tabbed
				.sliding-panel-frame
					.sliding-panel-group
						.sliding-panel
							.tab	
		*/
		prefs : { // to be overridden, extended or remain as default
			tab_selector_str : ".tab"			
		},
		configureTabLink : function ($a, sp_control_obj, target_x) {
			$a
				.click(function () {
					var $this = $(this);
					
					// search for journal-contents within sliding panel and hide if open
					/* js journals removed
					$sliding_panel
						.parent() // .sliding-panel-group
						.find('.journals').children('.journal-contents').slideUp('fast').siblings('.journal').removeClass('open');
					*/
					ais.tabs.slidePanelGroup(sp_control_obj, target_x);
					$this
						//.parent() // LI might be grandparent rather than parent
						.parents('li:first') // will this only pick up first li found?
						.addClass('this')
						.siblings()
						.removeClass('this');
					$this.blur();					
					return false; // overide mouse event
				})
				.hover(
				function () {
					$(this)
							.parents('li:first')
							.addClass("hover");
				}, 
				function () {
					$(this)
							.parents('li:first')
							.removeClass("hover");
				});
				
			return $a;
		},
		init : function (options) {
			var the, prefs;
			the = ais.tabs;
			prefs = $.extend(the.prefs, options);
			
			$('.tabbed')
				.each(function (tabbed_num) {
					var $tabbed_box, 
						$ul, 
						sp_control_obj, 
						sliding_panel_group, 
						$sliding_panels, 
						ctrl_hash_obj, // is there a better name for ctrl_hash_obj?
						total_width, 
						tab_index_counter, 
						ul_found;
						
					total_width = 0;
					tab_index_counter = 0;
					ul_found = false;
					
					$tabbed_box = $(this);
					$sliding_panels = $tabbed_box.find('.sliding-panel-frame > .sliding-panel-group > .sliding-panel');
					sliding_panel_group = $('.sliding-panel-frame > .sliding-panel-group', $tabbed_box).get(0); // get dom element rather than jQuery object
					
					sp_control_obj = { // function scoped for each .tabbed box
						//tab_index: 0,
						//selected_tab_index: 0,
						
						list: {}, // used to store id_objects
						
						// next properties used by: ais.tabs.slidePanelGroup
						speed: 20, 
						sliding_panel_group_el: sliding_panel_group,
						timeout: 0
					};
			
					//if ul.tabs doesn't exist create it, else re-use it
					$ul = $('ul.tabs', $tabbed_box);
					ul_found = ($ul.length !== 0);
					$ul = ul_found ? $ul : $('<ul class="horizontal header tabs"></ul>'); // ternary conditional operater
					//$ul = ($ul.length === 0) ? $('<ul class="horizontal header tabs"></ul>') : $ul; // ternary conditional operater
							
										
					$sliding_panels	// $('.sliding-panel-frame > .sliding-panel-group > .sliding-panel')
						.each(function (i) {
							var $sliding_panel, 
								$li, 
								$a, 
								tab_txt, 
								target_x,
								id, 
								id_obj, 
								$tab,
								tab_html_str, 
								inner_html_str, 
								$inner;
							
							
							$sliding_panel = $(this);
							target_x = 0 - total_width;
							total_width = total_width + this.offsetWidth; // $sliding_panel.get(0) === this

							// if .swoosh skip to next iteration, by returning true
							// and thus do not create a tab
							if ($sliding_panel.hasClass('swoosh')) {
								return true;
							}
							
							tab_txt = $sliding_panel
								.find('.tab')
								.eq(0) // only one .tab per .sliding-panel allowed
								.text();
							tab_txt = tab_txt ? tab_txt : "tab " + (tab_index_counter + 1);
							
							// if tab hasClass .delete [the black spot] then remove header
							$sliding_panel
								.find('.tab')
								.each(function () {
									$(this)
										.filter('.delete')
										.remove();
								});
							
							// this block allows for custom tabs to be prewritten in html, not necessarily using A links
							// requires:
							// UL.horizontal.tabs LI A 
							// or
							// UL.horizontal.tabs LI .tab 
							//
							// check if LI:eq(i) already exists, re-use if it does
							$li = $('li', $ul).eq(tab_index_counter);
							if ($li.length === 0) { // LI doesn't exist so define it
								$li = $("<li></li>");
								$a = $('<a href="#"></a>');							
								
								//$a = configureTabLink($a, tab_txt, sp_control_obj, target_x);
								$a.html(tab_txt); 
								the.configureTabLink($a, sp_control_obj, target_x);
								
								$li.append($a);
								$ul.append($li);
							} else {
								// LI exists, inside it may be an A or .tab
								$tab = $('.tab', $li);
								
								if ($tab.length === 0) { // .tab does not exist, assume there is an A to re-use
									$a = $('a', $li);
									$a.html(tab_txt); 
									the.configureTabLink($a, sp_control_obj, target_x);
									
								} else { // .tab exists
								
									
									if ($tab.is("a")) { // .tab is an A
										$tab.html(tab_txt); 
										the.configureTabLink($tab, sp_control_obj, target_x);
										
									} else { 
										// .tab is not an A (it's probably a span.tab)
										// so, prefer text in custom UL.tabs LI to text from leaf
										
										// check if .tab contains elements or just text
										if ($tab.children().length === 0) {
											// no html inside
											
											if ($tab.text().length !== 0) {
												// there is text within .tab to prefer

												tab_txt = $tab.text();// overide tab_text
												$tab.wrapInner('<a href="#"></a>'); // wrap contents of .tab with A (there might not be any)
											
											} else {
												// there is no text within .tab to prefer

												// put A into .tab
												$tab.append('<a href="#"></a>'); // wrapInner fails if text node is empty
											}
											$a = $('a', $tab);
											$a.html(tab_txt); 
											the.configureTabLink($a, sp_control_obj, target_x);
										
										} else {			
											$inner = $tab.children(":first"); 

											// if first child is empty then insert tab_txt
											// otherwise do not change its inner text/html
											inner_html_str = $inner.html();
											if (inner_html_str.length === 0) {
												$inner.html(tab_txt);
											} 
											
											$tab.wrapInner("<a href='#'></a>");
											
											// swap SPAN for A
											tab_html_str = $tab.html();
											$tab.replaceWith(tab_html_str);

											$a = $('a', $li);
											the.configureTabLink($a, sp_control_obj, target_x);
										}
										
									}	
								}								
							}

							// check for id on .sliding-panel
							id = this.id;
							if (id) {
								id_obj = {
									index: tab_index_counter,
									target_x: target_x,
									$li: $li
								};
								sp_control_obj.list[id] = id_obj;
							}
							
							tab_index_counter++;
						});	// eo: sliding_panels.each
					
					// resize Panel Group
					sliding_panel_group.style.width = total_width + "px";
					
					// change to run only if no id
					$ul
						.find('li:first')
						.addClass('this');
					
					
					// check if id matches tab	
					if (ais.url.hash.str.length > 0) { // then page has hash
						ctrl_hash_obj = sp_control_obj.list[ais.url.hash.str]; //sp_control_obj.list[id]
						if (ctrl_hash_obj) { // then hash matches id of a tab
							// set ctrls!
							ctrl_hash_obj.$li
								.addClass('this')
								.siblings()
								.removeClass('this');
							/*
								could use index instead of li?
								updateSignals = function() {
						$('.panel-nav', $sliding_panels).each(function() {
						$(this).children('a').eq(tab_index).addClass('this').siblings().removeClass('this');
						});
						};
							*/
							
							the.setPanelGroupX(sp_control_obj, ctrl_hash_obj.target_x);
							//document.window.moveTo(0,0);
						}	
					}
					
					// add UL if it did not already exist (otherwise don't move UL)
					if (!(ul_found)) {
						//$tabbed_box.prepend($ul);	
						$('.sliding-panel-frame', $tabbed_box).before($ul);
					}
					
				});	// eo: $('.tabbed').each	
		},
		setPanelGroupX : function (sliding_panel_control, pos_x) {
			var el;
			el = sliding_panel_control.sliding_panel_group_el;
			el.style.left = pos_x + "px";
		},
		slidePanelGroup : function (sliding_panel_control, target_x) { // el gets animated
			var el, 
				x, 
				repeat, 
				adjust, 
				denominator, 
				timeout_function;
			denominator = 8;
			repeat = true;
			el = sliding_panel_control.sliding_panel_group_el;
			if (sliding_panel_control.timeout) {
				clearTimeout(sliding_panel_control.timeout);
			}
			if (!el.style.left) {
				el.style.left = "0px";
			}
			x = parseInt(el.style.left, 10);
			if (x < target_x) {
				adjust = Math.ceil((target_x - x) / denominator);
				x = x + adjust;
				if (x > target_x) {
					x = target_x;
				}
			}
			if (x > target_x) {
				adjust = Math.ceil((x - target_x) / denominator);
				x = x - adjust;
				if (x < target_x) {
					x = target_x;
				}
			}
			if (x === target_x) {
				repeat = false;
			}
			el.style.left = x + "px";
			if (repeat) {
				timeout_function = function () {
					ais.tabs.slidePanelGroup(sliding_panel_control, target_x);
				};
				sliding_panel_control.timeout = setTimeout(timeout_function, sliding_panel_control.speed);
			} else {
				if (sliding_panel_control.timeout) {
					clearTimeout(sliding_panel_control.timeout);
				}
			}
		}
	};
	

	
    $(document).ready(function () {
	    ais.init();			
    }); // eo:ready
})(jQuery);
