/* 
	functions.js
	===============================================================
	The New Zealand Film Archive	
	CT Functions
	
	Created 14.04.2009 by DS
	Last Updated: See SVN	
	
	#t-* used to apply template level override of shared styles
	#st-* used to apply sub template level override of shared styles	
	
	To sort, search for '@'		
	Debugging is via the Firebug console: console.debug
  ===============================================================
*/

/*
	@ detect_browser()
	---------------------------------------------------------------		
	browser detection - fails in an external function for some unknown reason...
	jQuery browser detection, based on user string.		
	http://docs.jquery.com/Utilities/jQuery.browser
	http://webdevel.blogspot.com/2008/07/overview-of-jquerybrowser.html				
	
	note: detected version is in fact version of render engine
	
	parseFloat on browser version doesn't work without .substring(0,3)
	as eg 1.1.1 is not a number (only 1 decimal is allowed in a number)
	_______________________________________________________________
*/			

	function detect_browser()
	{				
		var jbrowserVersion = $.browser.version;
	
		var jbrowserVersionMajor = parseFloat( jbrowserVersion.substring(0,3) );
		var jbrowserVersionMinor = 0;		
		
		// alert( '$.browser.version = ' + $.browser.version + ', jbrowserVersionMajor = ' + jbrowserVersionMajor + ', jbrowserVersionMinor = ' + jbrowserVersionMinor );
		
		if ($.browser.mozilla)
		{						
			$.globals.isFirefox = true;		
			
			jbrowserVersionMinor = parseFloat( jbrowserVersion.substring(4,5) ); // substring starts at 4, ends at 5				
		
			// 1.5.0.1 = 1.8.0.1 (1.8, 0)
			// 2.0 = 1.8.1 (1.8, 1)			
			if ( (jbrowserVersionMajor >= 1.8) && (jbrowserVersionMinor == 1) )
			{		
				$.globals.isFirefox2up = true;
			}
			// 3.0.12 = 1.9.0.12 (1.9, 0)
			// 3.5.3 = 1.9.1.3 (1.9, 1)			
			if (jbrowserVersionMajor >= 1.9)
			{				
				$.globals.isFirefox3up = true;
			}					
			
			if ( ( $.globals.isFirefox2up ) && ( ! $.globals.isFirefox3up ) )
			{
				$.globals.isFirefox2 = true;
			}		
		}
		else if ($.browser.msie)
		{			
			$.globals.isIE = true;
		
			if (jbrowserVersion >= 6.0)
			{
				$.globals.isIE6up = true;				
			}			
			if ( (jbrowserVersion >= 6.0) && (jbrowserVersion < 7.0) )
			{
				$.globals.isIE6 = true;				
			}		
			if (jbrowserVersion >= 7.0)
			{
				$.globals.isIE7up = true;				
			}				
			if ( (jbrowserVersion >= 7.0) && (jbrowserVersion < 8.0) )
			{
				$.globals.isIE7 = true;				
			}	
			if (jbrowserVersion >= 8.0)
			{
				$.globals.isIE8up = true;				
			}				
		}
		else if ($.browser.safari)
		{					
			$.globals.isSafari = true;
		
			if ( (jbrowserVersion >= 522) || (jbrowserVersionMajor >= 522) ) // latter for mac safari 3
			{			
				$.globals.isSafari3up = true;				
			}				
			if ( (jbrowserVersion >= 528) || (jbrowserVersionMajor >= 528) )
			{		
				$.globals.isSafari4up = true;				
			}	
			else if ( (jbrowserVersion < 528) || (jbrowserVersionMajor < 528) )
			{
				$.globals.isSafari3down = true;					
			}				
		}		
		
		if ( $.globals.isFirefox2up || $.globals.isFirefox3up || $.globals.isIE6up || $.globals.isSafari3up )
		{
			isHiFi = true;
		}		
		
		return isHiFi;			
	}
		
/*
	@ detect_platform()
	---------------------------------------------------------------		
	_______________________________________________________________
*/			
		
	function detect_platform()
	{
		var ua = navigator.userAgent.toLowerCase(); 
		var platform = '';			
		
		if (ua.indexOf('win') != -1)
		{
			platform = 'win';
		}
		else if (ua.indexOf('mac') != -1)
		{
			platform = 'mac';
		}
		else if (ua.indexOf('unix') != -1)
		{
			platform = 'unix';
		}
		else if (ua.indexOf('linux') != -1)
		{
			platform = 'linux';
		}		
		
		return platform;
	}

/*	
	@ firebug console check
  ---------------------------------------------------------------
	Prevent errors in browsers that don't have the firebug console.
	
	src: http://www.contentwithstyle.co.uk/content/make-sure-that-firebug-console-debug-doesnt-break-everything
	_______________________________________________________________
*/

	function firebug_console_check()
	{
		if (!window.console) 
		{		
			// else just prevent errors
			window.console = new function() 
			{
				// commands from: http://getfirebug.com/logging.html	
				this.debug = function(str) {};
				this.error = function(str) {};
				this.info = function(str) {};
				this.warn = function(str) {};			
				this.log = function(str) {};
				this.dir = function(str) {};
			};
		}		
	}
	
/*	
	@ to_hex
	@ rgb_to_hex
	@ get_theme_color
  ---------------------------------------------------------------
	Gets the flash colour from the stylesheet.
	_______________________________________________________________
*/			

	var flash_reqdVersion;
	
	function to_hex(N) 
	{
		// http://www.linuxtopia.org/online_books/javascript_guides/javascript_faq/rgbtoHex.htm		
	 if (N === null) 
	 {
		 return "00";
	 }
	 N = parseInt(N, 10); 
	 if (N === 0 || isNaN(N)) 
	 {
		 return "00";
	 }
	 N = Math.max(0,N); 
	 N = Math.min(N,255); 
	 N = Math.round(N);
	 return ("0123456789ABCDEF".charAt((N-N%16)/16) + "0123456789ABCDEF".charAt(N%16));
	}		
	
	function rgb_to_hex(color)
	{	
		//console.debug( "rgb_to_hex('", color, "')");
	
		// FF formats the color as RGB, so we need to convert it to hex for sIFR
		if (color.indexOf('rgb') != -1)		
		{
			// rgb(193, 19, 30)
			var colors = color.replace('rgb(', '');
					colors = colors.replace(')', '');
					colors = colors.replace(' ', '');		
			
			// 193,19,30
			var colors_array = colors.split(',');
			var r = colors_array[0];
			var g = colors_array[1];						
			var b = colors_array[2];
	
			// http://www.linuxtopia.org/online_books/javascript_guides/javascript_faq/rgbtoHex.htm
			var hex_string = ('#' + to_hex(r) + to_hex(g) + to_hex(b));
			
			return (hex_string.toLowerCase());
		}
		else
		{			
			// IE already formats the color as hex
			return (color.toLowerCase());
		}
	}	

	function get_theme_colour(el)
	{				
		var theme_colours = [ 'aqua', 'blue', 'crimson', 'darkgreen', 'green', 'orange', 'pink', 'purple' ];
		var selectedColourName = '';
		
		$.each(theme_colours, function( intIndex, colourName ) 
		{
			if ( $(el).hasClass(colourName) )
			{
				selectedColourName = colourName;				
				
				if ( $(el).hasClass('flash') )
				{														
					parent_el = $(el + '.' + colourName);	 // eg [#vault.orange]
				}				
				else
				{		
					// .video added 30.09.2009
				
					if ( $(el + '.' + colourName + ' .flash').length > 0 )
					{
						parent_el = $(el + '.' + colourName + ' .flash');	 // eg [body.blue .flash]	
					}
					else if ( $(el + '.' + colourName + ' .video').length > 0 )
					{					
						parent_el = $(el + '.' + colourName + ' .video');	 // eg [body.blue .video]	
					}
				}
			}				
		});		

		var flash_controls_colour;

		if (parent_el)
		{
			flash_controls_colour = rgb_to_hex( $(parent_el).css('border-top-color') ).substring(1); // substring strips leading '#'
		}
		else
		{
			flash_controls_colour = 'ffffff';
		}

		//console.debug( "flash_controls_colour = ", flash_controls_colour, " (", selectedColourName, ")" );			

		return flash_controls_colour;			
	}
	
/*	
	@ listener_textfields()
  ---------------------------------------------------------------
	Variation on AK's function, recoded for jQuery
	Empty the search field onfocus, repopulate it with the default
	value onblur.
	
	Called on $(document).ready.
	_______________________________________________________________
*/		
	
	function listener_textfields() 
	{	
		//console.debug( "listener_textfields()" );	
		
		// onload
		$('input:text')
		.each(function() 
		{
			$(this)
			.data( 'defaultValue', $(this).attr('value') ); // store the value so that it is available onblur			
			
			//console.debug( "#", $(this).attr('id'), ".data.defaultValue = '", $(this).data('defaultValue'), "'" );					
		});
		
		// onfocus
		$('input:text')
		.bind('focus', function() 
		{							
			if ( $(this).val() === $(this).data('defaultValue') ) // if the default value is the same as the stored value
			{	
				$(this).val(''); // empty the displayed value
			}
		});
		
		// onblur		
		$('input:text')			
		.bind('blur', function() 
		{
			if ( $(this).val() === '' ) // if the field is empty
			{				
				$(this).val( $(this).data('defaultValue') );	// retrieve the stored value and use it to populate the field
			}
		});
	}		
	
/*	
	@ listener_fg_hover_states_incl_preload()
  ---------------------------------------------------------------
	Hover states for submit buttons.
	
	Called on $(document).ready
	
	Variation on:
	Src: http://www.atlantajones.com/2007/09/27/easy-reusable-image-rollovers-with-jquery/
	now using .data()
	
	To debug: Hovers sticky in IE
	_______________________________________________________________
*/	
	
	function listener_fg_hover_states_incl_preload(el)
	{	
		$(function()
		{		
			// Preload rollovers states			
			$(el)
			.each(function() 
			{											
				// Set the original src
				rollsrc = $(this).attr('src');													
				rollover = rollsrc.replace(/-off.gif$/ig,'-over.gif');
				$('<img/>')
				.attr('src', rollover);
				
				// console.info( "Preloaded: ", rollover );
				
				// save states with button img
				$(this)
				.data( 'offstate', rollsrc )
				.data( 'overstate', rollover );						
			});
			
			var el_parent = el.replace(' img', '');
			
			// Rollover
			
			var el_parent_type;
			
			if ( el.indexOf('a ') != -1 )
			{
				el_parent_type = 'a';
			}
			else if ( el.indexOf('button ') != -1 )
			{
				el_parent_type = 'button';
			}		
			
			$(el_parent)
			.bind ('mouseenter focus', function(e)
			{													
				switch ( e.target.tagName.toLowerCase() )
				{
					case el_parent_type :
					
						var img = $(this).children('img:first');			
						
						if ( $(img).attr('src') == $(img).data('offstate') )
						{
							$(img).attr( 'src', $(img).data('overstate') );
						}									
					
						break;
						
					case 'img' :
					
						$(e.target).parent().trigger('mouseenter');

						break;	
				}			 
			});
			
			// Rollout
			$(el_parent)
			.bind ('mouseleave blur', function(e)
			{							
				switch ( e.target.tagName.toLowerCase() )
				{										
					case el_parent_type :
					
						var img = $(this).children('img:first');
						
						if ( $(img).attr('src') == $(img).data('overstate') )
						{
							$(img).attr( 'src', $(img).data('offstate') );
						}									
					
						break;
						
					case 'img' :	
					
						$(e.target).parent().trigger('mouseleave');

						break;	
				}						
			});				

		});		
	}	
	
	function listener_content_news_hover()
	{				
		if ( $('#content-news').length > 0 )
		{
			// mouse user
			
			$('#content-news .news')
			.attr('tabindex', -1)
			.bind('mouseover', function()
			{
				$(this).addClass('news-over');				
				window.status = $(this).find('a').eq(0).attr('href');
			})
			.bind('mouseleave blur', function()
			{
				$(this).removeClass('news-over');
				window.status = '';
			});
			
			// keyboard user
		
			for (var n=0; n < $('#content-news .news').length; n++)
			{				
				$('#content-news .news').eq(n).find('a')
				.data('news_parent_index', n)
				.bind('focus', function()
				{
					var n = $(this).data('news_parent_index');
					$('#content-news .news').eq(n).trigger('mouseover');
				});				
				
				$('#content-news .news').eq(n).find('a:last')	
				.bind('blur', 
					function()
					{
						var n = $(this).data('news_parent_index');				
						$('#content-news .news').eq(n).trigger('mouseout');
					}
				);
			}
			
			// all users
			
			$('#content-news .news')			
			.bind('click', function(e)
			{
				var target = e.target;
				
				if ( (target.tagName.toLowerCase() == 'div') && (target.className.indexOf('news') != -1) ) 
				{		
					// $(target).find('a').eq(0).trigger('click'); // fails. whatever.
					
					if ( $(target).find('a').length > 0 )
					{
						var new_url = $(target).find('a').eq(0).attr('href');
						window.location = new_url;
					}
				}
				else if (target.tagName.toLowerCase() != 'a')
				{
					$(target).parent().trigger('click');										
				}				
			});
		}
	}
		
/*	
	@ generate_tooltip_html(el)
	@ simple_tooltip()
  ---------------------------------------------------------------
	Title to tooltip, on hover
	_______________________________________________________________
*/	

	function generate_tooltip_html(el)
	{		
		// append an html tooltip that we can then show/hide later
		
		//console.debug( "generate_tooltip_html('", $(el).parents('li:first').attr('class'), " a')" );	
		
		var is_enlargement;
		
		if ( $(el).parents('.enlargement') )
		{
			is_enlargement = true;
		}
		else
		{
			is_enlargement = false;
		}
		
		// create a hidden container for the tooltip_text		
		$(el)
		.append(
			$('<span/>')	
			.text(': ')
			.addClass('access')			
		)
		.append(		
			$('<em/>')
			.addClass('tooltip')
			.addClass('access')
			.append(
				$('<span/>')
				.addClass('pointer')	
			)			
		);
		
		if ( is_enlargement )
		{
			$(el).find('.tooltip')		
			.append(
				$('<span/>')
				.addClass('close')	
			);
		}
		
		// split the tooltip_text at ' ', and put each substring inside a <span/>
		
		string_text_array =  $(el).data('tooltip').split(' ');
			
		for (var s=0; s<string_text_array.length; s++)
		{					
			$(el).find('em:first')
			.append(
				$('<span/>')
				.addClass('word')
				.text( string_text_array[s] + ' ' )
			);
		}
		
		if ( is_enlargement )
		{	
			$(el).find('.tooltip')
			.append(
				$('<span/>')
				.addClass('clicktoopen')	
				.text('Click to open')
			);				
		}		
		
		// measure the pixel width of each .word, to determine which is the longest
		
		var longest_word_width = 0;
		
		$(el).find('.word')
		.each(function(e)
		{	
			var word_width;
		
			if ($.globals.isSafari)
			{
				word_width = $(this).attr('offsetWidth');				
			}
			else
			{
				word_width = $(this).attr('scrollWidth');	
			}
			
			if (word_width > longest_word_width)
			{
				longest_word_width = word_width;
			}
		});				
		
		// measure the width of the parent link, and get the horz stylesheet padding for the .tooltip
					
		var link_width = $(el).attr('offsetWidth');	// vs width(), as we need the total width, INCL horz padding
		
		if ( $(el).parents('.enlargement').length > 0 )
		{
			link_width += 46; // Add extra outdents to enlargement tooltips: 16 px LH outdent, 30px RH outdent	
		}		
		
		var tooltip = $(el).find('.tooltip');
		var tooltip_padding_left = $(tooltip).css('padding-left').replace('px', '');
		var tooltip_padding_right = $(tooltip).css('padding-right').replace('px', '');				
		var tooltip_padding = ( parseInt(tooltip_padding_left,10) + parseInt(tooltip_padding_right,10) );			

		var tooltip_min_width = (longest_word_width + tooltip_padding);				
		var link_width_safe = link_width;
		
		if (tooltip_min_width > link_width_safe)
		{
			// if the longest word makes the tooltip wider than the parent link			
			// (1) make the .pointer block the width of the link, so that the pointer is centered on the link rather than the tooltip
			// (2) make the tooltip block wide enough for the longest word	
			
			$(el).find('.pointer')
			.css( 'width', link_width ); 			
			
			link_width_safe = tooltip_min_width;
		}
		
		// if not the last text link, then add a pixel to the width of the tooltip
		
		var topup = 0;
		
		if ( $(el).parents('li:first').hasClass('last') )
		{
			topup = -1;
		}	
		
		$(tooltip)
		.css( 'width', ( link_width_safe - tooltip_padding + topup ) ); 
	}

	function simple_tooltip()
	{
		//console.debug( "simple_tooltip()" );
		
		// primary-nav
		
		$('#primary-nav ul a')		
		.each( function(index)
		{
			if ( $(this).attr('title').length > 0 )
			{
				// store title attribute as element data, then remove attribute
				$(this).data( 'tooltip', $(this).attr('title') );
				$(this).removeAttr( 'title' );
				
				generate_tooltip_html( $(this) );			
			}						
		});
		
		$('#primary-nav a')
		.bind('mouseenter hover focus', function()
		{					
			$(this).find('.tooltip')
			.removeClass('access');
		});
		
		$('#primary-nav a')
		.bind('mouseleave blur click', function()
		{				
			$(this).find('.tooltip')
			.addClass('access');		
		});	
		
		// enlargement

		$('.enlargement a')		
		.each( function(index)
		{
			// store title attribute as element data, then remove attribute
			$(this)
			.data( 'tooltip', $(this).attr('title') ) /* store title as data - lighbox has been hacked to pull this instead of the title (which is removed below) */
			.removeAttr( 'title' ) /* hide title so it doesn't show in addition to tooltip */
			.append(
				$('<span/>')			
				.addClass('enlarge')
			);		
			
			generate_tooltip_html( $(this) );				
		});
		
		$('.enlargement a')
		.bind('mouseenter hover focus', function()
		{					
			$(this).find('.tooltip')
			.removeClass('access');
		});
		
		$('.enlargement a')
		.bind('mouseleave blur click', function()
		{						
			$(this).find('.tooltip')
			.addClass('access');
		});	
		
		$('.enlargement a .tooltip')
		.bind('mouseleave blur click', function()
		{						
			$(this)
			.addClass('access');
		});		
		
		$('.enlargement a .close')
		.bind('click', function()
		{						
			$(this).parents('.tooltip:first')
			.addClass('access');
			
			return false; // close lightbox
		});				
		
	}
	
/*	
	@ ie_keyboard_access()
  ---------------------------------------------------------------
	jQuery replacement for a:focus
	_______________________________________________________________
*/		
	
	function ie_keyboard_access()
	{
		/* in combination with a.focus in stylesheets */
		
		if ($.globals.isIE6 || $.globals.isIE7)
		{		
			$('a')
			.bind('mouseenter hover focus', function()
			{
				$(this)
				.addClass('focus');
			})
			.bind('mouseleave blur click', function()
			{
				$(this)
				.removeClass('focus');
			});			
		}
	}
	
/*	
	@ ie_png_fix()
  ---------------------------------------------------------------
	Copied from http://plugins.jquery.com/project/iepngfix,
	then reduced to what I need
	
	Called by add_link_arrows();
	
	Note that this IE code is not suitable for variable-width/height
	replacements.
	_______________________________________________________________
*/	

	function ie_png_fix()
	{
		if ($.globals.isIE6)
		{
			$('img.arrow, #content .enlarge, a .tooltip .close').each(function()
			{																	 
				var bgIMG = $(this).css('background-image');
				
				if (bgIMG.indexOf(".png")!=-1)
				{
					var iebg = bgIMG.split('url("')[1].split('")')[0];
					$(this).css('background-image', 'none');
					$(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='image')";
					$(this).css('cursor', 'pointer'); // show PNG'd link as clickable
				}
			});				
		}
	}	
	
	function ie_lightbox_png_fix()
	{
		if ($.globals.isIE6)
		{
			$('jquery-lightbox').find('a').each(function()
			{																	 
				var bgIMG = $(this).css('background-image');
				
				if (bgIMG.indexOf(".png")!=-1)
				{
					var iebg = bgIMG.split('url("')[1].split('")')[0];
					$(this).css('background-image', 'none');
					$(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='image')";
				}
			});				
		}	
	}	
	
/*	
	@ add_link_arrows()
  ---------------------------------------------------------------
	Inject 1x1 pixel gifs, which are then styled via the CSS.
	_______________________________________________________________
*/	

	function add_link_arrows()
	{		
		//console.debug( "add_link_arrows()" );

		// add img.arrow to all links
		$('#content a, #related .module a, #related .event .more a, #footer .module a').each(function(i)
		{		
			// exceptions:
			if ( 
					( $(this).attr('href') ) && 
					( $(this).find('img').length < 1 ) &&
					( $(this).parent().get(0).tagName.toLowerCase() != 'h1' ) &&					
					( $(this).parent().get(0).tagName.toLowerCase() != 'h2' ) &&
					( $(this).parent().get(0).tagName.toLowerCase() != 'h3' ) &&
					( $(this).parent().get(0).tagName.toLowerCase() != 'h4' ) &&
					( $(this).parent().get(0).tagName.toLowerCase() != 'h5' ) &&
					( $(this).parent().get(0).tagName.toLowerCase() != 'h6' )	&&	
					( $(this).parents('td[class="event"]').length < 1 ) && 		
					( $(this).parents('ul[class="filter"]').length < 1 ) && 	
					( $(this).parents('div[class="anchor-nav"]').length < 1 ) && 						
					( $(this).parents('p[class="joomla-credit"]').length < 1 ) && 							
					( $(this).parents('dd[class*="category"]').length < 1 ) && 					
					( $(this).parents('div[class*="relatedlinks"]').length < 1 ) && 
					( $(this).parents('div[id="calendar-widget"]').length < 1 ) && /* was: [id*="calendar-widget"] */
					( !$(this).hasClass('button')) && 										
					( $(this).parents('.social-nav').length < 1 ) && 
					( $(this).parents('div[id*="rss"]').length < 1 ) && 
					( $(this).parents('table[class*="sortable"]').length < 1 ) &&					
					( $(this).parents('dd[class*="url"]').length < 1 ) &&
					( 
						( $(this).parents('div[class*="pagination"]').length < 1 ) || 
						( 
							( $(this).parents('div[class*="pagination"]').length > 0 ) &&
							( 
								( $(this).parents('li[class*="prev"]').length > 0 ) ||
								( $(this).parents('li[class*="next"]').length > 0 )
							)
						)
					)					 
			) 
			{			
				if ( ( $(this).parents('li[class*="prev"]').length > 0 ) || ( $(this).parents('p[class*="back"]').length > 0 ) || ( $(this).parents('div[class*="anchor-nav"]').length > 0 ) )
				{
					$(this)		
					.prepend(							
						$('<img/>')
						.attr('src', '/resources/ui/images/pixel.gif')						
						.attr('alt', '')
						.attr('width', 1)
						.attr('height', 1)
						.addClass('arrow')					
						//.css('border', '1px dotted red')
					);		
				}
				else
				{
					$(this)		
					.append(							
						$('<img/>')
						.attr('src', '/resources/ui/images/pixel.gif')						
						.attr('alt', '')
						.attr('width', 1)
						.attr('height', 1)
						.addClass('arrow')					
						//.css('border', '1px dotted red')
					);		
				}													
			}
		});
		
		ie_png_fix();
	}
	
/*	
	@ add_curves()
  ---------------------------------------------------------------
	Inject curve spans. These contain backgrounds assigned in the CSS.
	
	This applies to:
	
	A) any content that is user managed:
	- Image captions
	
	B) any content that is JS-generated
	- Flash captions
	
	PHP-generated content may use inline spans:
	- noFlash/Noscript warnings
	- t-calendar .header
	_______________________________________________________________
*/	

	function add_curves()
	{				
		$('.curved')
		.append(
			$('<span/>')
			.attr('class', 'tl')
			.html('&nbsp;')
		)
		.append(
			$('<span/>')
			.attr('class', 'tr')	
			.html('&nbsp;')	
		)	
		.append(
			$('<span/>')
			.attr('class', 'bl')					
			.html('&nbsp;')		
		)
		.append(
			$('<span/>')
			.attr('class', 'br')					
			.html('&nbsp;')
		);		
	}

	// bottom-left and bottom-right curves
	function add_curves()
	{				
		$('.curved-footer')
		.append(
			$('<span/>')
			.attr('class', 'bl')					
			.html('&nbsp;')		
		)
		.append(
			$('<span/>')
			.attr('class', 'br')					
			.html('&nbsp;')
		);		
	}
		
/*	
	@ button_print()
  ---------------------------------------------------------------
	Injects print button into DOM
	_______________________________________________________________
*/	
	
	function button_print()
	{
		//console.debug( "button_print()" );			

		if ( $('#tools ul').length > 0 )
		{
			$('#tools ul')
			.append(
				$('<li/>')
				.attr('id', 'print')
				.append(
					$('<button/>')		
					.bind('click', function()
					{
						window.print();
					})
					.append(
						$('<img/>')
						.attr('src', '/resources/ui/images/form-elements/buttons/print-page-off.gif')
						.attr('width', 110)
						.attr('height', 20)	
						.attr('alt', 'Print page. ')							
					)					
				)
			);
		}
		$('#print').type = 'button'; // .attr('type', 'button')			
	}
	
/*	
	@ ie_backtotop_patch()
  ---------------------------------------------------------------
	Fix for <a href="#top"> failure in IE6.
	_______________________________________________________________
*/		
	
	function ie_backtotop_patch()
	{
		if ($.globals.isIE6 || $.globals.isIE7)
		{
			$('#tools a').attr('href', '#top')
			.bind('click', function()
			{
				window.scroll(0,0);
			});			
		}
	}	
	
/*	
	@ listener_lightbox()
  ---------------------------------------------------------------	
	http://www.codymarquart.com/projects/jquery/listener/
	This function runs code every time the specified element is detected.
	
	Other options which were evaluated:
	
	http://salmonwebdesign.wordpress.com/2008/05/30/onelementready/
	- only runs first time element is detected
	
	http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/
	- stops checking for element after dom ready detected
	
	_______________________________________________________________
*/			
	
	function listener_lightbox(el)
	{		
		if ( $(el).find('a').length > 0 ) // only apply listeners if there are links to apply the lightbox to
		{							
			//console.debug( "listener_lightbox() for ", $(el).length, " sets" );					
				
				$(el).each( 
									 
					function()
					{											
						$('#' + $(this).attr('id') ).find('a').lightBox({
							overlayBgColor: '#000',
							overlayOpacity: 0.6,
							imageLoading: '/resources/ui/images/lightbox/lightbox-ico-loading.gif',
							imageBtnClose: ( !$.globals.isIE6 ? '/resources/ui/images/lightbox/close.png' : '/resources/ui/images/lightbox/close.gif' ),
							imageBtnPrev: ( !$.globals.isIE6 ? '/resources/ui/images/lightbox/previous.png' : '/resources/ui/images/lightbox/previous.gif' ),
							imageBtnNext: ( !$.globals.isIE6 ? '/resources/ui/images/lightbox/next.png' : '/resources/ui/images/lightbox/next.gif' ),
							containerResizeSpeed: 350,
							fixedNavigation: true,
							txtImage: 'Image',
							txtOf: 'of'
						});												
					}
				);
				
			// http://www.codymarquart.com/projects/jquery/listener/				

			// Listeners to reformat the lightbox after it is generated (ie after a lightbox-enhanced link is clicked)
									 
			$('body').listen("#lightbox-secNav",
			{								
				success:function(nodeFound)
				{				
				
					var lightboxWidth = $('#lightbox-container-image').width();
				
					$('#lightbox-container-image')
					.append(
							/* move the secondary nav (close button) container so that it is easier to style (fixes a FF2 issue) */
							$('#lightbox-secNav')
							.css( 'width', lightboxWidth )							
					);				
					
					if ($.globals.isIE6up)
					{
						$('#lightbox-secNav')
						.css( 'margin-left', ( -1 * (lightboxWidth/2) )	);	
					}
			
				}		 
			});	
			
			$('body').listen("#lightbox-nav",
			{
				success:function(nodeFound)
				{				
					if ($.globals.isIE6)
					{
						// prevent horz shift by Next button on click
						$('#lightbox-nav')
						.css( 'width', $('#lightbox-container-image-box').width() ); // else CSS width of 100% taken as width of parent - not including 20px padding
					}								
				}		 
			});				
			
			// Add hover state to Previous button
			$('body').listen("#lightbox-nav-btnPrev",
			{
				success:function(nodeFound)
				{						
					$('#lightbox-nav-btnPrev')		
					.unbind('mouseover, hover, mouseout, blur') // remove annoying assignments added by .hover() in jquery.lightbox.min.js
					.hover(
						function () // over
						{								
							$(this)
							.css('background-position', '0 -39px');							
						}, 
						function () // out
						{						
							$(this)
							.css('background-position', '0 0');							
						}
					);	
				}		 
			});		
			
			// Add hover state to Next button		
			$('body').listen("#lightbox-nav-btnNext",
			{
				success:function(nodeFound)
				{				
					$('#lightbox-nav-btnNext')
					.unbind('mouseover, hover, mouseout, blur') // remove annoying assignments added by .hover() in jquery.lightbox.min.js			
					.hover(
						function () // over
						{								
							$(this)
							.css('background-position', '100% -39px');							
						}, 
						function () // out
						{						
							$(this)
							.css('background-position', '100% 0');							
						}
					);	
				}		 
			});				
		}		
	}
	
/*	
	@ preload_bg_images()
  ---------------------------------------------------------------
	_______________________________________________________________
*/	


	function preload_bg_images()
	{
		//console.debug('preload_bg_images()');
		
		$('a').each( function()
		{				
			if ( $(this).css('background-image').indexOf('off') != -1 )
			{
				//console.info('** ', $(this).css('background-image').replace('-off', '-over') );
				
				var bg_src = $(this).css('background-image').replace( 'url(', '' );
						bg_src = bg_src.replace( ')', '' );	
				var	bg_src_over = bg_src.replace('-off', '-over');					
				
				$('<img/>')
				.attr( 'src', bg_src_over );
							
				//console.debug( "Preloaded: ", bg_src_over );
			}
		});		
	}	
	
/*	
	@ attach_script()
	@ attach_stylesheet()
	@ remove_stylesheet()	
  ---------------------------------------------------------------
	remove_stylesheet() added for IE8 but no longer used and
	currently untested
	_______________________________________________________________
*/		
	
	function attach_script(filename)
	{
		// attach the stylesheet that contains the styles to output
		$('head')
		.append(
			$('<script/>')
			.attr('type', 'text/javascript')
			.attr('src', filename)
		);
	}		
	
	function attach_stylesheet(filename, mediatype)
	{
		// attach the stylesheet that contains the styles to output
		$('head')
		.append(
			$('<link/>')
			.attr(
				{
					type: 'text/css',
					href: filename,
					rel: 'stylesheet',
					media: mediatype
				}
			)
		);
	}	
	
	function attach_stylesheet_ie8(filename, mediatype)
	{
		// attach the stylesheet that contains the styles to output
		$('head')
		.append('<link type="text/css" href="' + filename + '" rel="stylesheet" media="' + mediatype + '" />');
	}		
	
	function remove_stylesheet(filename)
	{
		// remove a stylesheet
		$('head').find('link').each(
			function()
			{
				if ( $(this).attr('href') == filename )
				{
					$(this).remove();
				}
			}
		)
	}		
	
/*	
	@ calendar globals
  ---------------------------------------------------------------
	_______________________________________________________________
*/	

	var events = new Array();	
	
/*	
	@ calendar_tooltip_get_xy()
  ---------------------------------------------------------------
	Get position of calling element
	
	Created 30.04.2008 by DS
	
	Src: http://www.quirksmode.org/js/findpos.html	
	_______________________________________________________________
*/		
	
	function calendar_tooltip_get_xy(el) 
	{		
		var curleft = 0;
		var curtop = 0;
		
		if (el.offsetParent) 
		{
			do {
				curleft += el.offsetLeft;
				curtop += el.offsetTop;
			}
			while (el = el.offsetParent); // this is not a syntax error
		}

		return [curleft, curtop];
	}		
	
/*	
	@ calendar_position_tooltip()
  ---------------------------------------------------------------
	Position tooltip to sit above calling link
	
	Created 30.04.2008 by DS
	Recoded into jQuery 19.05.2009 by DS	
	
	The original horz offset is no longer reqd,
	as there is now only one calendar in the #content 
	(the other is now in the #footer)
	_______________________________________________________________
*/		
		
	function calendar_position_tooltip(link_parent_id)
	{		
		var popup = $('#' + link_parent_id + ' .popup-wrapper'); 
			
		var popup_height = $('#' + link_parent_id).data('pwheight'); // use stored value, because popup-wrapper is resized to 1px high when .access is applied
		
		//console.debug( "$(#", link_parent_id, ").data('pwheight') = ", popup_height );
		
		var vert_offset;		

		if ($.globals.isIE6)
		{
			$(popup).css('top', 0); // reset
			
			var popup_top = calendar_tooltip_get_xy(popup)[1];	// popup not positioned yet, popup sits below calling A	

			var parent_top = calendar_tooltip_get_xy( $('#main-calendar-widget') )[1];	
			
			if ((popup_top - popup_height) < parent_top) // from baseline at top left of viewport
			{
				var random_offset = 18; // I can't calculate this, so if the text size is increased, there will be some overlap of the calling link
				vert_offset = 3 + random_offset; 
			}
			else
			{
				vert_offset = ('-' + (popup_height - 3));
			}													
		}
		else if ($.globals.isIE7up)
		{
			vert_offset = ('-' + (popup_height + 3));
		}			
		else
		{
			vert_offset = ('-' + (popup_height + 4));
		}			
		
		//console.debug( "vert_offset = " + vert_offset );
		
		$(popup).css('top', (vert_offset + 'px') );		
	}
	
/*	
	@ calendar_generate_tooltip()
  ---------------------------------------------------------------
	Generate tooltips containing event detail
	
	Created 30.04.2008 by DS
	Recoded into jQuery 19.05.2009 by DS		
	
	#
	
	Build a nested definition list,
	from the link title and the data in the events() array.			
	
	Because the popup content can vary, the popup must be allowed to
	scale vertically.
	
	To position the popup above and away from the link which created
	it, the height of the popup must be calculated, then applied
	via the CSS style.
	
	As the offsetHeight isn't known until the div is inserted into 
	the page, we start by hiding the div, then inserting the div 
	into the DOM, then we calculate the offsetHeight, and finally 
	we show the div in the correct position.
	
	The popup height used to be recalculated each time the popup is 
	shown, to prevent test resizing causing problems. This
	was found to be more accurate than simply using a relative
	unit (ie 'em') to set the vertical offset.
	In reality, this is not a common scenario, so this value 
	is no longer recalculated.
	
	.popup-liner and .popup-footer are only reqd by IE, so that the
	fixed height (.popup-footer) and variable height (.popup-liner) 
	sections of the dropshadow graphic can be separated.		
	
	#	
	
	Orig reading:
	http://www.jevents.net/component/option,com_events/Itemid,2/task,view_month/month,04/year,2008/lang,en_GB/

	And:

	CALENDAR EVENTS

	By default, Joomla outputs event popup JS as inline event handlers, but the code leaves a lot to be desired..
	So I've chosen to output script blocks inline, as hopefully this is a middleground that the backend developer can achieve.
	These inline blocks will populate the events array, so that this info is available on page load.
		
	format: 
		events[n] = new Array(); 
		events[n][nn] = new Array('Feature Film', '24/01/08', '19:00-20:00'. '$8.00'); 
		
	events[n]
		n is the date number
		
	events[n][nn]
		this refers to an event on this day
		
	events[n][nn] new Array('Feature Film'..
		the 'What' (Category) field for this event (the title is already known)
	
	events[n][nn] = new Array(..'24/01/08'
		the 'When' field for this event
		
	events[n][nn] = new Array(..'19:00-20:00'
		the 'Time' field for this event
		
	events[n][nn] = new Array(..'$8.00'
		the 'Price' field for this event										
		
	events[n][nn] = new Array(..'Somewhere'
		the 'Where' field for this event				
	_______________________________________________________________
*/		
	
	function calendar_generate_tooltip(link_parent_id)
	{			
		// Toggle the parent DD class to control CSS position (relative/absolute)
		$('#' + link_parent_id)
		.addClass('hover');			

		$('#' + link_parent_id).find('a:first')
		.data( 'title', $('#' + link_parent_id).find('a:first').attr('title') )
		.removeAttr('title'); // strip title so that it doesn't display		
					
		var popup_id = $('#' + link_parent_id).attr('id').split('-'); // [0: day-][1: 16][-][2: 1]

		n = popup_id[1];
		nn = popup_id[2];	
		
		$('#' + link_parent_id)
		.append(
			$('<div/>')
			.addClass('popup-wrapper')	
			.append(
				$('<div/>')
				.addClass('popup-liner')
				.append(
					$('<dl/>')
					.append(
						$('<dt/>')			
						.text( $('#' + link_parent_id).find('a:first').data('title') ) // [View details for '] .. [']									
					)
					.append(
						$('<dd/>')
						.addClass('category')
						.text( 'What: ' )
						.append(
							$('<span>'+events[n][nn][0]+'</span>') 
						)				
					)
					.append(
						$('<dd/>')
						.addClass('when')
						.text( 'When: ' )
						.append(
							$('<span>'+events[n][nn][1]+'</span>')
						)				
					)
					.append(
						$('<dd/>')
						.addClass('where')
						.text( 'Where: ' )
						.append(
							$('<span>'+events[n][nn][4]+'</span>')
						)						
					)
					.append(
						$('<dd/>')
						.addClass('time')
						.text( 'Time: ' )
						.append(
							$('<span>'+events[n][nn][2]+'</span>')
						)				
					)
					.append(
						$('<dd/>')
						.addClass('price')
						.text( 'Price: ' )
						.append(
							$('<span>'+events[n][nn][3]+'</span>')
						)			
					)									
				)							
			)
			.append(
				$('<span/>')
				.addClass('popup-footer')
			)	
		);
		
		// store the popup height as data			
		$('#' + link_parent_id)
		.data( 'pwheight', $('#' + link_parent_id + ' .popup-wrapper').height() ); // height when access not applied == real height :)			
		
		// hide the popup
		$('#' + link_parent_id + ' .popup-wrapper')
		.addClass('access');						
		
		// move the popup to the correct location			
		calendar_position_tooltip(link_parent_id);
		
		// show the popup			
		$('#' + link_parent_id + ' .popup-wrapper')
		.removeClass('access')
		.bgiframe(); // IE6 workaround for tooltip vs filter selects
	}	
	
/*	
	@ calendar_tooltip_listeners()
  ---------------------------------------------------------------
	Show tooltip when a calendar event is hovered over
	
	Created 30.04.2008 by DS
	Recoded into jQuery 19.05.2009 by DS	
	
	Orig reading:
	http://www.jevents.net/component/option,com_events/Itemid,2/task,view_month/month,04/year,2008/lang,en_GB/
	_______________________________________________________________
*/	
	
	function calendar_tooltip_listeners()
	{	
		if ( $('body').attr('id') == 't-calendar-month' )
		{
			$('#main-calendar-widget').find('table').eq(1).find('a').each( function()
			{
				$(this)				
				.hover(
					function () // over
					{						
						// Check whether the definition list has been built yet
						switch ( $(this).parent().find('dl').length > 0 )
						{
							case true:
							
								// Toggle the parent DD class to control CSS position (relative/absolute)
								$(this).parent()
								.removeClass('blur')
								.addClass('hover');	
								
								// Toggle the visibility of an existing popup DL
								$(this).parent().find('div:first')
								.removeClass('access');							
								
								break;
								
							case false:

								calendar_generate_tooltip( $(this).parent().attr('id') );									
								break;						
						}						
					},
					function () // off
					{								
						// Toggle the parent DD class to control CSS position (relative/absolute)
						$(this).parent()
						.removeClass('hover')
						.addClass('blur');
						
						// Toggle the visibility of an existing popup DL
						$(this).parent().find('div:first')
						.addClass('access');
					}
				);
			});
		}
	}		
	
/*	
	@ enable_tablesorting()
  ---------------------------------------------------------------
	_______________________________________________________________
*/		
	
	function enable_tablesorting()
	{
		var sortable_th = $('table.sortable').find('thead tr th'); 		
		
		$(sortable_th).each( 
			function(intIndex)
			{
				var th_text = $(this).children('span').text();				
				
				$(this).children('span')
				.wrap('<strong/>');	
				
				if (intIndex === 0)
				{
					$(this).children('strong:first')	
					.addClass('selected');					
				}							
				
				$(this).children('strong:first')			
				.attr('title', 'Sort table by \'' + th_text + '\' column. ')
				.bind('click', 
					function()
					{
						// remove 'selected' class from all TH STRONGs
						$(sortable_th).find('strong').each(
							function()
							{
								$(this).removeClass('selected');
							}
						);
					
						// add 'selected' class to this TH STRONG
						$(this)
						.addClass('selected');															
					}
				);
			}
		);							
		
    $('table.sortable').tablesorter({ 
        // sort on the first column, order asc 
        sortList: [[0,0]]
    }); 	
	}	
	
/*	
	@ enhance_enlargement_sets()
  ---------------------------------------------------------------
	Add a unique id to each set.
	_______________________________________________________________
*/		
	
	function enhance_enlargement_sets()
	{
		$('.enlargement').each(
		 	function(i)
			{
				$(this).attr( 'id', ( 'enlargement-set-' + i ) );
			}
		)
	}


/*
	@ add_facebook_like_button()
	---------------------------------------------------------------
	_______________________________________________________________
*/		

	(function($) 
	{
		$.fn.add_facebook_like_button = function(options) 
		{	
			// PLUGIN DEFAULTS
			$.fn.add_facebook_like_button.defaults = {
				app_id : 101508376585941,
				wall_message : 'This is the default message',
				wall_link : 'http://domain.ext',
				wall_image : false,
				wall_image_link : 'http://domain.ext',
				button_html : '<li class="social-facebook"><button id="social-facebook">Like on Facebook</button></li>',
				button_id : 'social-facebook'				
			};					
			
			options = $.extend($.fn.add_facebook_like_button.defaults,options);				
			
			// PLUGIN CODE
			return this.each( function() 
			{				
				// CHECK IF ALREADY ADDED
				if ( $(this).data('facebook_like_button_added') )
				{
					return;
				}		

				window.fbAsyncInit = function() {
					FB.init({appId: options.app_id, status: true, cookie: true, xfbml: true});
				};
				(function() {
					var e = document.createElement('script'); e.async = true;
					e.src = document.location.protocol +
						'//connect.facebook.net/en_US/all.js';
					document.getElementById('fb-root').appendChild(e);
				}());
			
				$(this).append(options.button_html);
			
				if ( options.wall_image && options.wall_image_link )
				{		
					$('#' + options.button_id).click( function(e) 
					{
						FB.ui( 
						{
							method: 'stream.publish',
							attachment: {
							    name: options.wall_name,
							    caption: options.wall_caption,
							    description: options.wall_description,
								href: options.wall_link,
								media: [{ 
									type: 'image', 
									src: options.wall_image, 
									href: options.wall_image_link
								}]
							}
						});
						
						e.preventDefault();		
					});
				}
				else if ( options.wall_image && !options.wall_image_link )
				{				
					$('#' + options.button_id).click( function(e) 
					{
						FB.ui( 
						{
							method: 'stream.publish',
							message: options.wall_message,
							attachment: {
							 	href: options.wall_link,
								media: [{ 
									'type': 'image', 
									'src': options.wall_image
								}]
							}
						});
						
						e.preventDefault();		
					});
				}
				else
				{
					$('#' + options.button_id).click( function(e) 
					{								
						FB.ui( 
						{
							method: 'stream.publish',
							message: options.wall_message,
							attachment: {
							    href: options.wall_link
							}
						});
						
						e.preventDefault();						
					});
				}	
				
				// MARK AS DONE
				$(this)
				.data('facebook_like_button_added', true);
			});			
		};
	})(jQuery);	
	
/*
	@ add_print_button()
	---------------------------------------------------------------
	_______________________________________________________________
*/	

	(function($) 
	{
		$.fn.add_print_button = function(options) 
		{		
			// PLUGIN DEFAULTS
			$.fn.add_print_button.defaults = {
				button_html : '<li class="social-print"><button id="social-print">Print</button></li>',
				button_id : 'social-print'				
			};			
			
			options = $.extend($.fn.add_print_button.defaults,options);					
			
			// PLUGIN CODE
			return this.each( function() 
			{				
				// CHECK IF ALREADY ADDED
				if ( $(this).data('print_button_added') )
				{
					return;
				}		
				
				$(this).append(options.button_html);
				
				$('#' + options.button_id).click( function() 
				{	
					window.print();
				});					
				
				// MARK AS DONE
				$(this)
				.data('print_button_added', true);			
			});			
		};
	})(jQuery);	

