﻿

/* Create support to handle namespaces and superclasses. */
/* Build the c9 namespace. */
var c9 = {
    extend: function(bc, sc, o) {
        var f = function() {};
        f.prototype = sc.prototype;
        bc.prototype = new f();
        bc.prototype.constructor = bc;
        bc.superclass = sc.prototype;
        for (var m in o)
            bc.prototype[m] = o[m];
    }
};

/* Build the namespace for the page class. */
c9.page = function() {

	/* Creates the namespace/class. */
	c9.page.superclass.init.apply(this, arguments);
	/* Calls the class initializer */
	this.initialize();
	
};

/* Extend jQuery with the page class. */
c9.extend(c9.page, jQuery, {

	/* Initialize the class. */
	initialize: function() {
		/* Initialize the page events */
		this.initEvents();
		/* Observe the links, ie with REL's. */
		this.observeLinks();
		/* Initialize observer for the search-input. */
		this.observeSearch();
		/* Initialize observer for the newsletter-input. */
		this.observeNewsletter();
		/* Initialize observer for the FAQ. */
		this.observeFAQ();
		/* Initialize the various tablesorters. */
		this.initTableSorter();
		/* Initialize the map */
		this.initMap();
		/* Initialize the page events */
		this.initAnalytics();
		
		
		/* Start the startpage posterslider-interval. */
		if ($('.imagewrapper .images').length > 0)
			posterSlide = setInterval(function() { c9.page.slidePoster($('.imagewrapper .images')) },6000);
	},


	/* 
	function: c9.page.initEvents()
	Initializes the page events - no inline events on this site!
	*/
	initEvents:function() {
		/* Handles the onmouseovers for the sorttables-headings. */
		$('table th.when, table th.what, table th.where').mouseover(function (sender) { c9.util.getCursor(sender.currentTarget); });
		
		/* Handles the expandable link in the booking form. */
		$('.form .wrapper .group a').mouseover(function (sender) { c9.util.getCursor(sender.currentTarget); });
		$('.form .wrapper .group a').click(function (sender) { c9.page.toggleFormExtras(); });
		
		/* Handles the validation of the submit button in all .forms */
		$('.form .wrapper .submit a').click(function (sender) { return c9.page.validateForm(sender.currentTarget); });
		
		/* Handles the images in the artists slideshows. */
		$('#slideshow .image').mouseover(function (sender) { c9.util.getCursor(sender.currentTarget); });
		$('#slideshow .image').click(function (sender) { $('#slideShowNext').click(); });
		
		/* Handles the buttons in the artists slideshows. */
		$('#slideshow #pager #slideShowLast').click(function (sender) { c9.page.slideImage(sender.currentTarget, 'left'); });
		$('#slideshow #pager #slideShowNext').click(function (sender) { c9.page.slideImage(sender.currentTarget, 'right'); });
		
		/* Handles all inputs and selects on the site (focus/blur effects) */
		$('input, select').focus(function (sender) { $(sender.currentTarget).css("color","black"); });
		$('input, select').blur(function (sender) { $(sender.currentTarget).css("color","#989898"); });
		
		/* Handles the submission of the  */
		$('#searchbutton').click(function (sender) { if ($('#searchinput').val() != $('#searchinput').attr('title')) { document.location.href='/sokresultat.aspx?search=' + $('#searchinput').val(); return false; } else { return false; } })
		
		/* Handle the startpage posterslider. */
		$('.imagewrapper .images').mouseover(function (sender) { c9.util.getCursor(sender.currentTarget); });
		$('.imagewrapper .dots').children().each(function (i) { $(this).click(function (sender) { clearInterval(posterSlide); this.blur(); c9.page.slidePoster($('.imagewrapper .images'), i); }); });

		
	},

	/* 
	function: c9.page.initAnalytics()
	Initializes Google Map if there is a #map-div on the page.
	*/
	initAnalytics: function() {

	},
	
	/* 
	function: c9.page.initMap()
	Initializes Google Map if there is a #map-div on the page.
	*/
	initMap: function() {
		
	
		/* Check if the #map-div exists. */
		if ($('#map').length > 0) {

			

			var latitude = $('#hfLatitude').val();
			var longitude = $('#hfLongitude').val();
			var zoom = ($('#hfZoom').val().length > 0 ? $('#hfZoom').val() : 12);
			
			if (latitude.length > 0) {
				if (longitude.length > 0) {
					
					/* Check if the browser is compatible. */
					if (typeof GBrowserIsCompatible != 'undefined') {
						if (GBrowserIsCompatible()) {
						
							/* Declare the map variable and initiate it. */
							var map = new GMap2(document.getElementById('map'));
							
							/* Add the large map control. */
							map.addControl(new GLargeMapControl());
							/* Add the Map Type Control. */
							map.addControl(new GMapTypeControl());
							
							/* Declare the arena as a LatLng. */
							var arena = new GLatLng(parseFloat(latitude), parseFloat(longitude));
							/* Add a marker as overlay. */
							map.addOverlay(new GMarker(arena));
							
							/* Make the mapwrapper visible. */
							$('#mapwrapper').removeClass('invisible');
							/* Make the map visible. */
							$('#map').removeClass('invisible');
							/* Center the map on the arena with the fetched zoom level. */
							map.setCenter(arena, parseFloat(zoom));
							
						}
					}
				}
			}
			else {
				/* Remove the #mapwrapper from the page. */
				$('#mapwrapper').remove();
				/* Remove the #map from the page. */
				$('#map').remove();
			}

		}
	},


	/* 
	function: c9.page.initTableSorter()
	Initializes the various tablesorters on the site. 
	Every table with sort functionality gets their settings here.
	*/
	initTableSorter: function() {
		/* Extend the tablesorter. */
		this.extendTableSorter();
		/* Check if any table.modulegigs exists on the page. */
		if ($("table.modulegigs"))
		/* Make the table sortable with the tablesorter-function found in /scripts/jquery.tablesorter.min.js. */
			$("table.modulegigs").tablesorter({
				/* Make the first column sortable by the extension 'dates', the third should not be sortable. */
				headers: { 0: { sorter: 'dates' }, 2: { sorter: false} },
				/* Attach the zebra-widget to make the table css-classes odd/even. */
				/* This will be depricated later on. */
				widgets: ['zebra'],
				/* Hook the tableSorterTextExtraction to the contents of the table-datas. */
				textExtraction: this.tableSorterTextExtraction,
				/* Make sure the list is sorted by ascending dates by default. */
				sortList: [[0, 0]]
			});
		/* Check if any table.modulegenregigs exists on the page. */
		if ($("table.modulegenregigs"))
		/* Make the table sortable with the tablesorter-function found in /scripts/jquery.tablesorter.min.js. */
			$("table.modulegenregigs").tablesorter({
				/* Make the first column sortable by the extension 'dates', the fourth should not be sortable. */
				headers: { 0: { sorter: 'dates' }, 3: { sorter: false} },
				/* Attach the zebra-widget to make the table css-classes odd/even. */
				/* This will be depricated later on. */
				widgets: ['zebra'],
				/* Hook the tableSorterTextExtraction to the contents of the table-datas. */
				textExtraction: this.tableSorterTextExtraction,
				/* Make sure the list is sorted by ascending dates by default. */
				sortList: [[0, 0]]
			});
		/* Check if any table.startgigs exists on the page. */
		if ($("table.startgigs"))
		/* Make the table sortable with the tablesorter-function found in /scripts/jquery.tablesorter.min.js. */
			$("table.startgigs").tablesorter({
				/* Make the first column sortable by the extension 'dates', the fourth should not be sortable. */
				headers: { 0: { sorter: 'dates' }, 3: { sorter: false} },
				/* Attach the zebra-widget to make the table css-classes odd/even. */
				/* This will be depricated later on. */
				widgets: ['zebra'],
				/* Hook the tableSorterTextExtraction to the contents of the table-datas. */
				textExtraction: this.tableSorterTextExtraction,
				/* Make sure the list is sorted by ascending dates by default. */
				sortList: [[0, 0]]
			});
	},

	/* 
	function: c9.page.extendTableSorter()
	Extends the tablesorter(), prepares dates and handles innerHTML-data to get a wider range of sortable data.
	*/
	extendTableSorter: function() {

		/* Parser used to handle ShortDates with three-letter-months */
		/* This parser is not multilingual! See 'var m=[,,,]' below... */
		$.tablesorter.addParser({
			/* set a unique id */
			id: 'dates',
			is: function(s) {
				/* return false so this parser is not auto detected */
				return false;
			},
			format: function(s) {
				/* split the string */
				var a = s.split(' ');
				/* get month number */
				a[1] = this.getMonth(a[1]);
				/* glue and return as a new date */
				return new Date(a.reverse().join("/")).getTime();
			},
			getMonth: function(s) {
				/* Array of the dates, this solution is not multilingual! */
				var m = ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec']
				/* Set the length of the array - usually it's twelve. Duh! */
				var l = m.length;
				/* Itterate through the array */
				for (var i = 0; i < l; i++) {
					/* Check whether the month name and array item matches */
					if (m[i] == s.toLowerCase()) {
						/* Return the number of the matched month */
						return (i + 1);
					}
				}
			},
			/* set type, either numeric or text */
			type: 'numeric'
		});

		/* Handle data with childnodes. */
		/* Primary used with the date-columns in the gig-lists. */
		this.tableSorterTextExtraction = function(node) {
			/* Build the return string. */
			/* If there's one child node, strip the HTML from it. */
			var r = ((typeof node.childNodes[0] != 'undefined') ? node.childNodes[0].innerHTML : node.innerHTML);
			/* Repeat if there's a second child and append it to the return string. */
			r += ' ' + ((typeof node.childNodes[1] != 'undefined') ? node.childNodes[1].innerHTML : '');
			/* Repeat if there's a third child and append it to the return string. */
			r += ' ' + ((typeof node.childNodes[2] != 'undefined') ? node.childNodes[2].innerHTML : '');

			/* Send the return string back. */
			return r;
		}
	},

	/*
	function: c9.page.observeLinks()
	Hadles the a-links, 
	*/
	observeLinks : function() {
		$('a').click(function() {
			if($(this).attr('rel') == 'external')
			{
				window.open($(this).attr('href'));
				return false;
			}
		})
	},
	
	/* 
	function: c9.page.observeSearch()
	Handles the focus/blur events on #searchinput, also listens to ENTER-submission
	*/
	observeSearch: function() {
		/* Check if the #searchinput actually exisits in the page. */
		if ($('#searchinput')) {
			/* Populate the example-function found in /scripts/jquery.example.min.js */
			$('#searchinput').example(function() {
				/* Return the title-attribute fron the HTML. */
				return $(this).attr('title');
			});
			/* Observe the keypresses while typing. */
			$('#searchinput').keypress(function(e) {
				/* Check if the pressed key is ENTER. */
				if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
					/* Click the submit-button to post the form. */
					$('#searchbutton').click();
					/* Disallow the keypress. */
					return false;
				} else {
					/* Allow the keypress. */
					return true;
				}
			});
		}
	},

	/* 
	function: c9.page.observeFAQ()
	Handles the click/mouseover events in the '.faqlisting' lists.
	*/
	observeFAQ: function() {
		/* Check if '.faqlisting li.faqitem' exist in page. */
		if ($('.faqlisting li.faqitem')) {
			/* Observe the click-event on all links. */
			$('.faqlisting li.faqitem a').click(function(sender) {
				/* Show/hide all siblings to the anchor. */
				$(this).siblings().toggleClass("hidden");
				/* Blur the anchor. */
				$(this).blur();
			});
			/* Observe the mouseover-event on all links. */
			$('.faqlisting li.faqitem a').mouseover(function(sender) {
				/* Get a crossbrowser cursor. */
				c9.util.getCursor(this);
			});
		}
	},

	/* 
	function: c9.page.observeNewsletter()
	Handles the focus/blur events on #newslettersignupinput, also listens to ENTER-submission
	*/
	observeNewsletter: function() {
		/* Check if any .newslettersignupinput actually exisits in the page. */
		if ($('.newslettersignupinput')) {
			/* Populate the example-function found in /scripts/jquery.example.min.js */
			$('.newslettersignupinput').example(function() {
				/* Return the title-attribute fron the HTML. */
				return $(this).attr('title');
			});
			/* Observe the keypresses while typing. */
			$('.newslettersignupinput').keypress(function(e) {
				/* Check if the pressed key is ENTER. */
				if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
					/* Click the submit-button to post the form. */
					document.location.href = $('.newslettersignupbutton').attr('href');
					/* Disallow the keypress. */
					return false;
				} else {
					/* Allow the keypress. */
					return true;
				}
			});
		}
	},
	
	/* Used to keep track of which image thats visible ATM. */
	slideImageNumber : 1 ,
	
	/*
	function: c9.page.slideImage()
	param: sender = the element that executes the event
	param: direction = string to determine the direction of the slide. 
	Changes the image to the next/previous in a slideshow. 
	*/
	slideImage: function(sender, direction) {
		
		/* Blur the sender-element. */
		sender.blur();
		
		/* Make 'this' accessible from within nestled functions. */
		var that = this;
		/* Get the total count of the image (div) array */
		var imageCount = $(sender).parent('#pager').siblings().length;
		
		/* Itterate through the image (div) array */
		$(sender).parent('#pager').siblings().each(function(i) {
			
			/* Make sure that the current div aint hidden - to find the active one. */
			if (!$(this).hasClass('hidden')) {
				
				/* Handle the directions. */
				switch (direction) {
					/* If the direction is 'left'. */
					case 'left':
						/* Make sure the previous element exists. */
						if ($(this).prev().hasClass('imagewrapper')) {
							/* Remove the hidden-css-class. */
							$(this).prev().toggleClass('hidden');
							/* Update the c9.page.slideImageNumber by subtracting one. */
							that.slideImageNumber = that.slideImageNumber -1;
						}
						/* If the previous element doesn't exist... */
						else {
							/* Remove the hidden-css-class of the last element in the array. */
							$(sender).parent('#pager').siblings(':last').toggleClass('hidden');
							/* Since the active element is the last one, set c9.page.slideImageNumber to the arrays length (+1) */
							that.slideImageNumber = imageCount;
						}
						/* Break the case. */
						break;	
				
					/* If the direction is 'right'. */
					case 'right':
						/* Make sure the next element exists. */
						if ($(this).next().hasClass('imagewrapper')) {
							/* Remove the hidden-css-class. */
							$(this).next().toggleClass('hidden');
							/* Update the c9.page.slideImageNumber by adding one. */
							that.slideImageNumber = that.slideImageNumber +1;
						}
						/* If the next element doesn't exist... */
						else {
							/* Remove the hidden-css-class of the first element in the array. */
							$(sender).parent('#pager').siblings(':first').toggleClass('hidden');
							/* Since the active element is the first one, set c9.page.slideImageNumber to 1 */
							that.slideImageNumber = 1;
						}
						/* Break the case. */
						break;
				}
				
				/* Hide the current (past) div. */
				$(this).toggleClass('hidden');
				
				/* Break the each-itteration. */
				return false;
			}
			
		});
		
		/* Update the pager-element. */
		$(sender).siblings('span').html(this.slideImageNumber + '/' + imageCount);
		
	},
	
	/* Used to remember the last left-position in the startpage posterslider*/
	nLeft:0,
	
	/*
	function: c9.page.slidePoster()
	param: sender = the element that executes the event
	param: number = the number of the element that should be selected.
	Changes the image to the next/previous in the startpage posterslider. 
	*/
	slidePoster: function(sender, number) {
	
		/* Get the total count of the image (div) array */
		var imageCount = $(sender).children().length;
		
		/* Extra addon to the calculation, needed to get crossbrowser functionality. */
		var addon = 300;
		
		/* The slider should move to a set position. */
		if (typeof number != 'undefined') {
			
			/* Calculate the nLeft variable. */
			this.nLeft = ($(sender).scrollLeft() + $(sender).children(0).outerWidth()) * (number);
			
			/* Fetch the active dot. */
			var dDot = $(sender).siblings().children('.active');
			/* Fetch the active tape. */
			var dTape = $(sender).parent().siblings().children('.active');
			
			/* Inactivate the current dot. */
			dDot.removeClass('active');
			/* Inactivate the current tape. */
			dTape.removeClass('active');
			
			/* The set position isn't the last one. */
			if (number != imageCount) {
				/* Execute the right-to-left-animation */
				$(sender).animate( { left: -this.nLeft + 'px' }, 1000 );
				$(sender).siblings().children(':eq(' + number + ')').addClass('active');
				$(sender).parent().siblings().children(':eq(' + number + ')').addClass('active');
			}
			else {
				/* Execute the left-to-right-animation */
				$(sender).animate( { left: '0px' }, 500 );
				/* Activate the first dot. */
				$(sender).siblings().children(':first').addClass('active');
				/* Activate the first tape. */
				$(sender).parent().siblings().children(':first').addClass('active');
			}
			
		}
		else {
		
			/* Repopulate the nLeft variable based on the coming left position */ 
			this.nLeft = $(sender).scrollLeft() + $(sender).children(0).outerWidth() + this.nLeft;
		
			/* Fetch the active dot. */
			var dDot = $(sender).siblings().children('.active');
			/* Fetch the active tape. */
			var dTape = $(sender).parent().siblings().children('.active');
			
			/* Check that the new nLeft-value is lower then the full width of the wrapper. */
			if (this.nLeft + addon < $(sender).outerWidth()) {
				/* Execute the right-to-left-animation */
				$(sender).animate( { left: -this.nLeft + 'px' }, 1000 );
				/* Inactivate the current dot. */
				dDot.removeClass('active');
				/* Inactivate the current tape. */
				dTape.removeClass('active');
				/* Activate the next dot. */
				dDot.next().addClass('active');
				/* Activate the next tape. */
				dTape.next().addClass('active');
			}
			else {
				/* Execute the left-to-right-animation */
				$(sender).animate( { left: '0px' }, 1000 );
				/* Inactivate the current dot. */
				dDot.removeClass('active');
				/* Inactivate the current tape. */
				dTape.removeClass('active');
				/* Activate the first dot. */
				$(sender).siblings().children(':first').addClass('active');
				/* Activate the first tape. */
				$(sender).parent().siblings().children(':first').addClass('active');
				/* Reset the nLeft. */
				this.nLeft = 0;
			}
        }
        
        /* Return and halt. */
		return false;		
	},
	
	
	/* 
	function: c9.page.validateForm()
	param: sender = the anchor that triggers the filter
	Returns true if all validation is OK.
	A generic form validator. Triggered onclick on the submit buttons and hooked on all elements with matched css-classes.	
	
	This function could be rewritten in a more generic way!
	*/
	validateForm: function(sender) {
		/* Declare the return variable. */
		var r = true;
		/* Declare and populate a regexp used to validate e-mail addresses*/
		var reEmail = new RegExp(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/);
		/* Declare and populate a regexp used to validate numeric values*/
		var reNumeric = new RegExp(/^-?[0-9]+$/);
		/* Declare and populate a regexp used to validate swedish postal numbers, 'nn nnn' */
		var rePostal = new RegExp(/^\d{3} \d{2}$/);
		
		/* Check if any elements exists with the class 'valtext'. */
		/* Used to check that the elements value is'nt empty. */
		if ($('.valtext')) {
			/* Itterate through all matched elements. */
			$('.valtext').each(function(i, sender) {
				/* Check that the value is'nt empty. */
				if ($(this).val().length == 0) {
					/* Add the 'error' class to the element. */
					$(this).addClass('error');
					/* Add the 'error' class to all siblings */
					$(this).siblings().addClass('error');
					/* Set the return variable to false. */
					r = false;
				}
				else {
					/* Remove the 'error' class to the element. */
					$(this).removeClass('error');
					/* Remove the 'error' class to all siblings */
					$(this).siblings().removeClass('error');
				}
			});
		}
		/* Check if any elements exists with the class 'valemail'. */
		/* Used to check that the elements value is'nt empty and is a valid e-mail address. */
		if ($('.valemail')) {
			/* Itterate through all matched elements. */
			$('.valemail').each(function(i, sender) {
				/* Match the elements value with the reEmail regexp. */
				if (!$(this).val().match(reEmail)) {
					/* Add the 'error' class to the element. */
					$(this).addClass('error');
					/* Add the 'error' class to all siblings */
					$(this).siblings().addClass('error');
					/* Set the return variable to false. */
					r = false;
				}
				else {
					/* Remove the 'error' class to the element. */
					$(this).removeClass('error');
					/* Remove the 'error' class to all siblings */
					$(this).siblings().removeClass('error');
				}
			});
		}
		
		/* Check if any elements exists with the class 'valnumericoptional'. */
		/* Used to check that the elements value is a numeric value. This form element is optional */
		if ($('.valnumericoptional')) {
			/* Itterate through all matched elements. */
			$('.valnumericoptional').each(function(i, sender) {
				/* Check if the element has any value*/
				if ($(this).val().length > 0)
				{
					/* Match the elements value with the reEmail regexp. */
					if (!$(this).val().match(reNumeric)) {
						/* Add the 'error' class to the element. */
						$(this).addClass('error');
						/* Add the 'error' class to all siblings */
						$(this).siblings().addClass('error');
						/* Set the return variable to false. */
						r = false;
					}
					else {
						/* Remove the 'error' class to the element. */
						$(this).removeClass('error');
						/* Remove the 'error' class to all siblings */
						$(this).siblings().removeClass('error');
					}
				}
				else {
					/* Remove the 'error' class to the element. */
					$(this).removeClass('error');
					/* Remove the 'error' class to all siblings */
					$(this).siblings().removeClass('error');
				}
			});
		}
		
		/* Check if any elements exists with the class 'valpostaloptional'. */
		/* Used to check that the elements value is a numeric value, with or without space. This form element is optional */
		if ($('.valpostaloptional')) {
			/* Itterate through all matched elements. */
			$('.valpostaloptional').each(function(i, sender) {
				/* Check if the element has any value*/
				if ($(this).val().length > 0)
				{
					if($(this).val().length == 5)
						$(this).val($(this).val().substring(0,3) + ' ' + $(this).val().substring(3,5));
						
					/* Match the elements value with the reEmail regexp. */
					if (!$(this).val().match(rePostal)) {
						/* Add the 'error' class to the element. */
						$(this).addClass('error');
						/* Add the 'error' class to all siblings */
						$(this).siblings().addClass('error');
						/* Set the return variable to false. */
						r = false;
					}
					else {
						/* Remove the 'error' class to the element. */
						$(this).removeClass('error');
						/* Remove the 'error' class to all siblings */
						$(this).siblings().removeClass('error');
					}
				}
				else {
					/* Remove the 'error' class to the element. */
					$(this).removeClass('error');
					/* Remove the 'error' class to all siblings */
					$(this).siblings().removeClass('error');
				}
			});
		}
		
		/* Check if any elements exists with the class 'valselect'. */
		/* Used to check that the selected value is'nt empty. */
		if ($('.valselect')) {
			/* Itterate through all matched elements. */
			$('.valselect').each(function(i, sender) {
				/* Check that the selected value is'nt empty. */
				if ($("option:selected",this).val().length == 0) {
					/* Add the 'error' class to the element. */
					$(this).addClass('error');
					/* Add the 'error' class to all siblings */
					$(this).siblings().addClass('error');
					/* Set the return variable to false. */
					r = false;
				}
				else {
					/* Remove the 'error' class to the element. */
					$(this).removeClass('error');
					/* Remove the 'error' class to all siblings */
					$(this).siblings().removeClass('error');
				}
			});
		}
		
		if (r) {
			$(sender).parents('.form .wrapper').children('div.error').addClass('hidden');
		}
		else {
			$(sender).parents('.form .wrapper').children('div.error').removeClass('hidden');
		}
		
		/* Send back the return variable. */
		return r;
	},
	
	/* 
	function: c9.page.filterCalendarRows()
	param: sender = the <select> that triggers the filter
	Used to populate data used when filtering of the calendar tables.
	*/
	filterCalendarRows: function(sender) {

		/* Declare a array to hold key/value of the current columns */
		var filterArray = new Array();

		/* Select all select-objects in the same level of the HTML. */
		$(sender).siblings('select').andSelf().each(function(i, dselect) {
			/* Populate the filterArray with the current set of key/value */
			filterArray[i] = new Array($(dselect).attr('class'), dselect.options[dselect.selectedIndex].value);
		})

		/* Make it happend! */
		c9.page.filterCalendarData(sender, filterArray);
	},

	/* 
	function: c9.page.filterCalendarData()
	param: sender = the <select> that triggers the filter
	param: filterArray = a two-dimensional array with key/value of the filters.
	Used to execute filtration of calendar tables.
	*/
	filterCalendarData: function(sender, filterArray) {

		/* Declare variable to use to iterate through visible rows. */
		var iter = 0;

		/* Select all table-rows in the current table. */
		$(sender).parents('table').find("tbody tr").each(function(i, dtr) {

			/* Declare variable used to handle visible/hidden. */
			var show = true;

			/* Select all table-datas in the current table-row. */
			$(dtr).find('td').each(function(j, dtd) {
				/* itterate thourgh the filterArray. */
				for (i = 0; i < filterArray.length; i++) {
					/* Check if the current table-data has the current filter-key. */
					if ($(dtd).hasClass(filterArray[i][0])) {
						/* Check if the current filter-value is found inside the contents of the table-data. */
						if (filterArray[i][1].length > 0 && dtd.innerHTML.indexOf(filterArray[i][1]) == -1) {
							show = false;
							return;
						}
					}
				}
			});

			/* Test if the row should be visible. */
			if (show) {
				/* Remove any old class-attributes. */
				$(dtr).removeAttr('class');
				/* Test if the row is even or odd with modulus. */
				if (iter % 2) {
					/* Add the 'odd' CSS-class. */
					$(dtr).attr('class', 'odd');
				}
				else {
					/* Add the 'even' CSS-class. */
					$(dtr).attr('class', 'even');
				}
				iter++;
			}
			else {
				/* Add the 'hidden' CSS-class. */
				$(dtr).attr('class', 'hidden');
			}
		});
	},

	/* 
	function: c9.page.toggleFormExtras()
	Used to show and hide extra fields on various forms, ie on the book-an-artist form. 
	*/
	toggleFormExtras: function() {
		/* Show/hide the '.form #aSimplifyShow'. Visible by default. */
		$('.form #aSimplifyShow').toggleClass('hidden');
		/* Show/hide the '.form #aSimplifyHide'. Hidden by default. */
		$('.form #aSimplifyHide').toggleClass('hidden');
		/* Show/hide the '.form #divSimplity'. Hidden by default. */
		$('.form #divSimplity').toggleClass('hidden');
	}

});

/* Build the namespace for the util class. */
c9.util = function() {

	/* Creates the namespace/class. */
	c9.util.superclass.init.apply(this, arguments);
	/* Calls the class initializer. */
	this.initialize();
	
};

/* Extend jQuery with the util class. */
c9.extend(c9.util, jQuery, {
	
	/* Initialize the class. */
	initialize: function() {
	
	},

	/* 
	function: c9.util.getCursor()
	param: dDom = the object who trigges the event
	Used to handle crossbrowser hand/pointer cursors on onmouseovers.
	*/
	getCursor : function(sender)
	{	
		/* If the broswer is compatible with Internet Explorer. */
		if (document.all) {
			/* Set the cursor as 'hand'. */
			$(sender).css('cursor','hand');
		}
		else {
			/* Set the cursor as 'pointer'. */
			$(sender).css('cursor','pointer');
		}
	}
});

$(document).ready(function() {
	/* Set a namespace for/and load the generic util-functions. */
	c9.util = new c9.util();
	/* Set a namespace for/and load the specific page-functions. */
	c9.page = new c9.page();
});    
