/********************************************************
 *							*
 *	Site javascript for musicalchairs.info		*
 *							*
 *	Generic multipurpose functions come first.	*
 *	Site specific functions follow.			*
 *							*
 ********************************************************/


// Generic Functions
//------------------

function trim (str, charlist) {
    // Strips whitespace from the beginning and end of a string. From PHP.JS; dual MIT/GPL license at http://phpjs.org/pages/license
    // 
    // version: 905.1001
    // discuss at: http://phpjs.org/functions/trim
    var whitespace, l = 0, i = 0;
    str += '';
    
    if (!charlist) {
        // default list
        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
    } else {
        // preg_quote custom list
        charlist += '';
        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
    }
    
    l = str.length;
    for (i = 0; i < l; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }
    
    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }
    
    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}

function isValidEmail(str)
	{
/**
 * Email validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */

	var at="@";
	var dot=".";
	var lat=str.indexOf(at);
	var lstr=str.length;
	if (str.indexOf(at)==-1){
//	   alert("Invalid E-mail ID")
	   return false;
	}

	if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
//	   alert("Invalid E-mail ID")
	   return false;
	}

	if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
//	    alert("Invalid E-mail ID")
	    return false;
	}

	 if (str.indexOf(at,(lat+1))!=-1){
//	    alert("Invalid E-mail ID")
	    return false;
	 }

	 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
//	    alert("Invalid E-mail ID")
	    return false;
	 }

	 if (str.indexOf(dot,(lat+2))==-1){
//	    alert("Invalid E-mail ID")
	    return false;
	 }
	
	 if (str.indexOf(" ")!=-1){
//	    alert("Invalid E-mail ID")
	    return false;
	 }

	return true;				
	}

/*
 * Generic ajax functions
 * ----------------------
 */

/* Load ajax directly into the DOM
 * element is the id (as string) or the DOM element to load the response into.
 *
 * Adds the query string in script_qry to the url, which itself may or may not contain a query string.
 * Page anchors within the url are discarded.
 */
function makeRequest(url, script_qry, element, callback)
	{
	var http_request, posn; 
	
	http_request = false;
	
	// Discard page anchor
	posn = url.indexOf('#');
	if (posn != -1) url = url.substr(0, posn);
	
	// Append query string
	if (script_qry) url = url + (url.indexOf('?') == -1 ? '?' : '&') + script_qry;

	if (window.XMLHttpRequest)
		{ // Mozilla, Safari, ...
		http_request = new XMLHttpRequest();
		}
	else if (window.ActiveXObject)
		{ // IE6
		try	{
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
			}
		catch (e)
			{
			try	{
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
				}
			catch (e)
				{
				}
			}
		}

	if (!http_request)
		{
		alert('Unable to make Ajax request. You may have an obsolete web browser.');
		return false;
		}

	http_request.onreadystatechange = function()
		{
		var el;
		el = (typeof(element) == 'string') ? document.getElementById(element) : element;
	
		if (el && http_request.readyState == 4)
			{
			if (http_request.status == 200)
				{
				el.innerHTML = http_request.responseText;
				if (typeof(callback) == 'function') callback();
				}
			else el.innerHTML = 'Internal error - please try again';
			}
		};

	http_request.open('GET', url, true);
	http_request.send(null);
	}

function clearResult(element)
	{
	var el;
	el = (typeof(element) == 'string') ? document.getElementById(element) : element;
	el.innerHTML = '';
	}

/*
 * Low level ajax
 * --------------
 */

function rawRequest(url, script_qry, callback)
	{
	var http_request; 
	
	http_request = false;		

	// Discard page anchor
	posn = url.indexOf('#');
	if (posn != -1) url = url.substr(0, posn);
	
	// Append query string
	if (script_qry) url = url + (url.indexOf('?') == -1 ? '?' : '&') + script_qry;

	if (window.XMLHttpRequest)
		{ // Mozilla, Safari, ...
		http_request = new XMLHttpRequest();
		}
	else if (window.ActiveXObject)
		{ // IE6
		try	{
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
			}
		catch (e)
			{
			try	{
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
				}
			catch (e)
				{
				}
			}
		}

	if (!http_request)
		{
		alert('Unable to make Ajax request. You may have an obsolete web browser.');
		return false;
		}

	http_request.onreadystatechange = function() { rawResult(http_request, callback); };
	http_request.open('GET', url, true);
	http_request.send(null);
	}

function rawResult(http_request, callback)
	{
	if (http_request.readyState == 4)
		{
		if (http_request.status == 200) callback(http_request.responseText)
		else alert('Internal error - please try again');
		}
	}

/* Traversing the DOM
   ------------------
 */
 
/* Get the closest element that matches the tag name given
 */
function closest(el, tag, classname)
	{
	var parentEl;
	
	tag = tag.toLowerCase();
	parentEl = el.parentNode;
	while (parentEl.tagName.toLowerCase() != tag || (classname && parentEl.className != classname))
		{
		parentEl = parentEl.parentNode;
		if (!parentEl || !parentEl.tagName) return null; /* !! Early Return !! */
		}
	return parentEl;
	}

/**
 * getElements(classname, tagname, root):					From http://www.davidflanagan.com/javascript5/display.php?n=15-4&f=15/04.js
 * Return an array of DOM elements that are members of the specified class,
 * have the specified tagname, and are descendants of the specified root.
 * 
 * If no classname is specified, elements are returned regardless of class.
 * If no tagname is specified, elements are returned regardless of tagname.
 * If no root is specified, the document object is used.  If the specified
 * root is a string, it is an element id, and the root
 * element is looked up using getElementsById()
 */
function getElements(classname, tagname, root) {
    // If no root was specified, use the entire document
    // If a string was specified, look it up
    if (!root) root = document;
    else if (typeof root == "string") root = document.getElementById(root);
    
    // if no tagname was specified, use all tags
    if (!tagname) tagname = "*";

    // Find all descendants of the specified root with the specified tagname
    var all = root.getElementsByTagName(tagname);

    // If no classname was specified, we return all tags
    if (!classname) return all;

    // Otherwise, we filter the element by classname
    var elements = [];  // Start with an emtpy array
    for(var i = 0; i < all.length; i++) {
        var element = all[i];
        if (isMember(element, classname)) // isMember() is defined below
            elements.push(element);       // Add class members to our array
    }

    // Note that we always return an array, even if it is empty
    return elements;

    // Determine whether the specified element is a member of the specified
    // class.  This function is optimized for the common case in which the 
    // className property contains only a single classname.  But it also 
    // handles the case in which it is a list of whitespace-separated classes.
    function isMember(element, classname) {
        var classes = element.className;  // Get the list of classes
        if (!classes) return false;             // No classes defined
        if (classes == classname) return true;  // Exact match

        // We didn't match exactly, so if there is no whitespace, then 
        // this element is not a member of the class
        var whitespace = /\s+/;
        if (!whitespace.test(classes)) return false;

        // If we get here, the element is a member of more than one class and
        // we've got to check them individually.
        var c = classes.split(whitespace);  // Split with whitespace delimiter
        for(var i = 0; i < c.length; i++) { // Loop through classes
            if (c[i] == classname) return true;  // and check for matches
        }

        return false;  // None of the classes matched
    }
}

/*
 * Form handling functions
 * -----------------------
 */
 
function radioValue(formEl, name)
	{
	var radioButtons, i;

	radioButtons = formEl.elements[name];
	for(i= 0; i<radioButtons.length; ++i) if(radioButtons[i].checked) return radioButtons[i].value;
	return null;
	}

/* 
 * Graphical functions
 * -------------------
 */

// Toggle the display of an element on or off
function toggle(el_id)
	{
	var el, oldStyleDisplay;
	el = document.getElementById(el_id);
	if (el)
		{
		if (window.getComputedStyle) oldStyleDisplay = window.getComputedStyle(el,null).display; // W3C
		else if (el.currentStyle) oldStyleDisplay = el.currentStyle.display; // IE
		else if (el.style.display) oldStyleDisplay = el.style.display; // Fallback 1
		else oldStyleDisplay = 'block'; // Fallback 2
		
		if (oldStyleDisplay == 'none')
			{ // Show
			if (el.originalDisplay) el.style.display = el.originalDisplay; // Restoring previous display parameter (see below)
			else el.style.display = 'block';
			}
		else
			{ // Hide
			el.originalDisplay = oldStyleDisplay; // Store current display property for restoring later
			el.style.display = 'none';
			}
		}
	}

// Scrollbar width. Assumes all scrollbars are the same width as a <body> scrollbar.	
function scrollbarWidth()
	{
	var overflowStyle, width;
	
	overflowStyle = document.body.style.overflow;
	document.body.style.overflow = 'hidden';

	width = document.body.clientWidth;
	document.body.style.overflow = 'scroll';
	width -= document.body.clientWidth;
 
	if (overflowStyle) document.body.style.overflow = overflowStyle;
	else document.body.style.overflow = '';
 
	return width;
	}

// The ultimate offsetLeft relative to the viewport (this origin may be browser dependant)
function ultimateOffsetLeft(el)
	{
	var offset;
	offset = 0;

	if (el)
		{
		while (el.offsetParent)
			{
			offset += el.offsetLeft;
			el = el.offsetParent;
			}
		}

	return offset;
	}

// The ultimate offsetTop relative to the viewport (this origin may be browser dependant)
function ultimateOffsetTop(el)
	{
	var offset;
	offset = 0;

	if (el)
		{
		while (el.offsetTop)
			{
			offset += el.offsetTop;
			el = el.offsetParent;
			}
		}

	return offset;
	}

/**
 * Geometry.js: portable functions for querying window and document geometry 	From http://www.davidflanagan.com/javascript5/display.php?n=14-2&f=14/Geometry.js
 *
 * This module defines functions for querying window and document geometry.
 * 
 * getWindowX/Y(): return the position of the window on the screen
 * getViewportWidth/Height(): return the size of the browser viewport area
 * getDocumentWidth/Height(): return the size of the document.
 * getHorizontalScroll(): return the position of the horizontal scrollbar
 * getVerticalScroll(): return the position of the vertical scrollbar
 *
 * Note that there is no portable way to query the overall size of the 
 * browser window, so there are no getWindowWidth/Height() functions.
 * 
 * IMPORTANT: This module must be included in the <body> of a document		Note modification to run after window.onload instead.
 *            instead of the <head> of the document.
 */

var Geometry = {};

function geometry() {
	if (window.screenLeft) { // IE and others
	    Geometry.getWindowX = function() { return window.screenLeft; };
	    Geometry.getWindowY = function() { return window.screenTop; };
	}
	else if (window.screenX) { // Firefox and others
	    Geometry.getWindowX = function() { return window.screenX; };
	    Geometry.getWindowY = function() { return window.screenY; };
	}

	if (window.innerWidth) { // All browsers but IE
	    Geometry.getViewportWidth = function() { return window.innerWidth; };
	    Geometry.getViewportHeight = function() { return window.innerHeight; };
	    Geometry.getHorizontalScroll = function() { return window.pageXOffset; };
	    Geometry.getVerticalScroll = function() { return window.pageYOffset; };
	}
	else if (document.documentElement && document.documentElement.clientWidth) {
	    // These functions are for IE6 when there is a DOCTYPE
	    Geometry.getViewportWidth =
		function() { return document.documentElement.clientWidth; };
	    Geometry.getViewportHeight = 
		function() { return document.documentElement.clientHeight; };
	    Geometry.getHorizontalScroll = 
		function() { return document.documentElement.scrollLeft; };
	    Geometry.getVerticalScroll = 
		function() { return document.documentElement.scrollTop; };
	}
	else if (document.body.clientWidth) {
	    // These are for IE4, IE5, and IE6 without a DOCTYPE
	    Geometry.getViewportWidth =
		function() { return document.body.clientWidth; };
	    Geometry.getViewportHeight =
		function() { return document.body.clientHeight; };
	    Geometry.getHorizontalScroll =
		function() { return document.body.scrollLeft; };
	    Geometry.getVerticalScroll = 
		function() { return document.body.scrollTop; };
	}

	// These functions return the size of the document.  They are not window 
	// related, but they are useful to have here anyway.
	if (document.documentElement && document.documentElement.scrollWidth) {
	    Geometry.getDocumentWidth =
		function() { return document.documentElement.scrollWidth; };
	    Geometry.getDocumentHeight =
		function() { return document.documentElement.scrollHeight; };
	}
	else if (document.body.scrollWidth) {
	    Geometry.getDocumentWidth =
		function() { return document.body.scrollWidth; };
	    Geometry.getDocumentHeight =
		function() { return document.body.scrollHeight; };
	}
}

if (window.addEventListener) // DOM Level 2 API
	window.addEventListener("load", geometry, 0);
else if (window.attachEvent) // IE workaround
	window.attachEvent("onload", geometry);

// Cross browser style and dimension retrieval
//
// NB:
//	.currentStyle gives the cascaded styles (e.g. '1em') for IE (and Opera, but that isn't used here). Here we create a dummy div and measure it to convert to pixels.
// 	.computedStyle in standards compliant browsers gives computed (pixel) styles.
//
function computedDimension(element, property) {
	/* 
	 * Return computed dimension as a number (in pixels)
	 */
	if (window.getComputedStyle)
		{
		// W3C compliant
		return parseInt(document.defaultView.getComputedStyle(element, null).getPropertyValue(property));
		}
	else if (element.currentStyle)
		{
		/* 
		 * Following is needed for IE up to 7 (IE8 to be tested)
		 */
		var IE_cascadedStyle, hyphen, tempDiv, dimension;
		while ((hyphen = property.indexOf('-')) != -1)
			{ // Convert to camelcase e.g. 'margin-top' becomes 'marginTop'
			// Need to repeat as some properties have >1 hyphen. 
			property = property.substr(0, hyphen).concat(property.charAt(hyphen+1).toUpperCase()).concat(property.substr(hyphen+2));
			}
		IE_cascadedStyle = element.currentStyle[property];
		if (IE_cascadedStyle.match(/^\d+px$/))
			{
			// If cascaded style in pixels, bale out here.
			return parseInt(IE_cascadedStyle);
			}
		else if (IE_cascadedStyle.match(/\d+(%|em|ex|pt|pc|in|mm|cm)$/))
			{
			/* If cascaded style is a length (other than specified
			 * in pixels, then create a dummy block element with this width,
			 * and measure .offsetWidth 
			 */
			tempDiv = document.createElement("div");
        		tempDiv.style.width = IE_cascadedStyle;
		        document.body.appendChild(tempDiv);
		        dimension = tempDiv.offsetWidth;
		        document.body.removeChild(tempDiv);
		        return dimension;
			}
		else
			// Not a dimension - just return value
			return IE_cascadedStyle;
		}
	}
function computedStyle(element, property) {
	/* Return style as computed for w3c compliant browsers, 
	 * or as cascaded for IE. Beware of situations where this will
	 * give differing results (dimensions).
	 */
	if (window.getComputedStyle)
		return document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
	else if (element.currentStyle)
		return element.currentStyle[property];
	}

// Date functions not in dates.min.js //
// -----------------------------------//

function date ( format, timestamp ) {

    // Format a local date/time  
    // 
    // version: 910.813
    // discuss at: http://phpjs.org/functions/date
    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: MeEtc (http://yass.meetcweb.com)
    // +   improved by: Brad Touesnard
    // +   improved by: Tim Wiel
    // +   improved by: Bryan Elliott
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: David Randall
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +  derived from: gettimeofday
    // +      input by: majak
    // +   bugfixed by: majak
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   input by: Alex
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // %        note 1: Uses global: php_js to store the default timezone
    // *     example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
    // *     returns 1: '09:09:40 m is month'
    // *     example 2: date('F j, Y, g:i a', 1062462400);
    // *     returns 2: 'September 2, 2003, 2:26 am'
    // *     example 3: date('Y W o', 1062462400);
    // *     returns 3: '2003 36 2003'
    // *     example 4: x = date('Y m d', (new Date()).getTime()/1000); // 2009 01 09
    // *     example 4: (x+'').length == 10
    // *     returns 4: true
    // *     example 5: date('W', 1104534000);
    // *     returns 5: '53'
    
    var that = this;
    var jsdate=(
        (typeof(timestamp) == 'undefined') ? new Date() : // Not provided
        (typeof(timestamp) == 'object') ? new Date(timestamp) : // Javascript Date()
        new Date(timestamp*1000) // UNIX timestamp (auto-convert to int)
    ); // , tal=[]
    var pad = function (n, c){
        if ( (n = n + "").length < c ) {
            return new Array(++c - n.length).join("0") + n;
        } else {
            return n;
        }
    };
    var _dst = function (t) {
        // Calculate Daylight Saving Time (derived from gettimeofday() code)
        var dst=0;
        var jan1 = new Date(t.getFullYear(), 0, 1, 0, 0, 0, 0);  // jan 1st
        var june1 = new Date(t.getFullYear(), 6, 1, 0, 0, 0, 0); // june 1st
        var temp = jan1.toUTCString();
        var jan2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        temp = june1.toUTCString();
        var june2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
        var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);

        if (std_time_offset === daylight_time_offset) {
            dst = 0; // daylight savings time is NOT observed
        } else {
            // positive is southern, negative is northern hemisphere
            var hemisphere = std_time_offset - daylight_time_offset;
            if (hemisphere >= 0) {
                std_time_offset = daylight_time_offset;
            }
            dst = 1; // daylight savings time is observed
        }
        return dst;
    };
    var ret = '';
    var txt_weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday"];
    var txt_ordin = {1: "st", 2: "nd", 3: "rd", 21: "st", 22: "nd", 23: "rd", 31: "st"};
    var txt_months =  ["", "January", "February", "March", "April",
        "May", "June", "July", "August", "September", "October", "November",
        "December"];

    var f = {
        // Day
            d: function (){
                return pad(f.j(), 2);
            },
            D: function (){
                var t = f.l();
                return t.substr(0,3);
            },
            j: function (){
                return jsdate.getDate();
            },
            l: function (){
                return txt_weekdays[f.w()];
            },
            N: function (){
                //return f.w() + 1;
                return f.w() ? f.w() : 7;
            },
            S: function (){
                return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th';
            },
            w: function (){
                return jsdate.getDay();
            },
            z: function (){
                return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0;
            },

        // Week
            W: function (){

                var a = f.z(), b = 364 + f.L() - a;
                var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;

                if (b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
                    return 1;
                } 
                if (a <= 2 && nd >= 4 && a >= (6 - nd)){
                    nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
                    return that.date("W", Math.round(nd2.getTime()/1000));
                }
                
                var w = (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);

                return (w ? w : 53);
            },

        // Month
            F: function (){
                return txt_months[f.n()];
            },
            m: function (){
                return pad(f.n(), 2);
            },
            M: function (){
                var t = f.F();
                return t.substr(0,3);
            },
            n: function (){
                return jsdate.getMonth() + 1;
            },
            t: function (){
                var n;
                if ( (n = jsdate.getMonth() + 1) == 2 ){
                    return 28 + f.L();
                }
                if ( n & 1 && n < 8 || !(n & 1) && n > 7 ){
                    return 31;
                }
                return 30;
            },

        // Year
            L: function (){
                var y = f.Y();
                return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0;
            },
            o: function (){
                if (f.n() === 12 && f.W() === 1) {
                    return jsdate.getFullYear()+1;
                }
                if (f.n() === 1 && f.W() >= 52) {
                    return jsdate.getFullYear()-1;
                }
                return jsdate.getFullYear();
            },
            Y: function (){
                return jsdate.getFullYear();
            },
            y: function (){
                return (jsdate.getFullYear() + "").slice(2);
            },

        // Time
            a: function (){
                return jsdate.getHours() > 11 ? "pm" : "am";
            },
            A: function (){
                return f.a().toUpperCase();
            },
            B: function (){
                // peter paul koch:
                var off = (jsdate.getTimezoneOffset() + 60)*60;
                var theSeconds = (jsdate.getHours() * 3600) +
                                 (jsdate.getMinutes() * 60) +
                                  jsdate.getSeconds() + off;
                var beat = Math.floor(theSeconds/86.4);
                if (beat > 1000) {
                    beat -= 1000;
                }
                if (beat < 0) {
                    beat += 1000;
                }
                if ((String(beat)).length == 1) {
                    beat = "00"+beat;
                }
                if ((String(beat)).length == 2) {
                    beat = "0"+beat;
                }
                return beat;
            },
            g: function (){
                return jsdate.getHours() % 12 || 12;
            },
            G: function (){
                return jsdate.getHours();
            },
            h: function (){
                return pad(f.g(), 2);
            },
            H: function (){
                return pad(jsdate.getHours(), 2);
            },
            i: function (){
                return pad(jsdate.getMinutes(), 2);
            },
            s: function (){
                return pad(jsdate.getSeconds(), 2);
            },
            u: function (){
                return pad(jsdate.getMilliseconds()*1000, 6);
            },

        // Timezone
            e: function () {
/*                var abbr='', i=0;
                if (this.php_js && this.php_js.default_timezone) {
                    return this.php_js.default_timezone;
                }
                if (!tal.length) {
                    tal = this.timezone_abbreviations_list();
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return tal[abbr][i].timezone_id;
                        }
                    }
                }
*/
                return 'UTC';
            },
            I: function (){
                return _dst(jsdate);
            },
            O: function (){
               var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
               t = (jsdate.getTimezoneOffset() > 0) ? "-"+t : "+"+t;
               return t;
            },
            P: function (){
                var O = f.O();
                return (O.substr(0, 3) + ":" + O.substr(3, 2));
            },
            T: function () {
/*                var abbr='', i=0;
                if (!tal.length) {
                    tal = that.timezone_abbreviations_list();
                }
                if (this.php_js && this.php_js.default_timezone) {
                    for (abbr in tal) {
                        for (i=0; i < tal[abbr].length; i++) {
                            if (tal[abbr][i].timezone_id === this.php_js.default_timezone) {
                                return abbr.toUpperCase();
                            }
                        }
                    }
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return abbr.toUpperCase();
                        }
                    }
                }
*/
                return 'UTC';
            },
            Z: function (){
               return -jsdate.getTimezoneOffset()*60;
            },

        // Full Date/Time
            c: function (){
                return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P();
            },
            r: function (){
                return f.D()+', '+f.d()+' '+f.M()+' '+f.Y()+' '+f.H()+':'+f.i()+':'+f.s()+' '+f.O();
            },
            U: function (){
                return Math.round(jsdate.getTime()/1000);
            }
    };

    return format.replace(/[\\]?([a-zA-Z])/g, function (t, s){
        if ( t!=s ){
            // escaped
            ret = s;
        } else if (f[s]){
            // a date function exists
            ret = f[s]();
        } else {
            // nothing special
            ret = s;
        }
        return ret;
    });
}

function todaysDate(input_id)
	{
	document.getElementById(input_id).value = date('d/m/Y');
	}


/************************************************
 *						*
 *	Site specific functions follow		*
 *	------------------------------		*
 *						*
 ************************************************/
 

/* 
 * Output functions
 * ----------------
 */

function getCountryVAT()
	{
	makeRequest("ajax_php/get-vat-reg.php", "code=" + document.advert_add.invoice_country.value, "vat_num");
	}

function adjustPrice(discipline)
	{
	if (typeof(disciplineCount) == 'undefined') disciplineCount = 0;

	if(discipline.checked == true) disciplineCount++;
	else disciplineCount--;

	getPrice();
	}

function getPrice()
	{
	var x;
	x = document.getElementById('invoice_price');
	if (x)
		{
		var prices;

		if(disciplineCount == 0) prices = "&euro;0 / $0 / &pound;0";
		else if(disciplineCount == 1) prices = "&euro;60 / $80 / &pound;40";
		else if(disciplineCount > 6) prices = "&euro;180 / $240 / &pound;120";
		else prices = "&euro;135 / $180 / &pound;90";

		if(disciplineCount == 1) x.innerHTML = '<strong>' + disciplineCount + '</strong> disclipline: <strong>' + prices + '</strong>';
		else x.innerHTML = '<strong>' + disciplineCount + '</strong> discliplines: <strong>' + prices + '</strong>';
		}
	}

/*
 * Add job form functions
 * ----------------------
 */

function changeJobCategory(key)
	{
	makeRequest('ajax_php/get-job-type.php', 'job_category='+key, 'job-type-container');
	if (document.getElementById('job-categories-dynamic')) makeRequest('ajax_php/get-job-subtypes.php', 'job_category='+key, 'job-categories-dynamic');
	}

function changeJobInfoFormat(key)
	{
	var divs, i, el;
	divs = document.getElementById('job-info-input').getElementsByTagName('div');
	for (i=0; i<divs.length; ++i) divs[i].style.display = 'none';
	document.getElementById('job-info-input-'+key).style.display = "block";
	
	if (key == 'htm')
		{
		el = document.getElementById('job-text-input');
		el.style.display = 'block';	
		el.style.height = '220px';
		}
	else
		{
		document.getElementById('job-text-input').style.display = 'none';
		}
	}

// For admin-job-add
function selectJobCountry(response)
	{
	if (response.match(/[a-z]{2}/))
		{
		var select, options, i;
		select = document.getElementById('job_country');
		options = select.options;
		for (i=0; i < options.length; ++i)
			{
			if (options[i].value == response) options[i].selected = true;
			else options[i].selected = false;
			}
		select.disabled = false;
		}
	}

/* 
  Artificially highlight first item in third level menu if no sibling hovered on (used with menu_access.min.js)
  ------------------------------------------------------------------------------
  
  Also ensure third level menu is in viewport if possible.
*/

function highlight3 (self)
	{
	var uls, lis, topY, bottomY, viewportBottomY, viewportHeight;

	// Highlighting stage 1: On second level - highlight default entry in third level
	uls = self.getElementsByTagName('ul');
	if (self.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'ul' && uls.length)
		{
		// Reset margin-top (see below)
		uls[0].style.marginTop = '';
		
		// Highlighting
		lis = uls[0].getElementsByTagName('li');
		lis[0].className = lis[0].className + ' hover3';

		// Also ensure third level is in viewport if it will fit.
		topY = ultimateOffsetTop(uls[0]);
		bottomY = topY + uls[0].offsetHeight;
		viewportHeight = Geometry.getViewportHeight();
		viewportBottomY = Geometry.getVerticalScroll() + viewportHeight;
		if (bottomY > viewportBottomY)
			{
			if (uls[0].offsetHeight > viewportHeight)
				{
				// <ul> won't actually fit anyway but vertically position at top of screen
				uls[0].style.marginTop = (Geometry.getVerticalScroll() - topY - uls[0].offsetTop).toString().concat('px');
				}
			else
				{
				// Move <ul> vertically upwards so bottom edge is just above the bottom of the viewport
				uls[0].style.marginTop = (viewportBottomY - bottomY - 2).toString().concat('px');
				}
			}
		}
		
	// Highlighting stage 2: On third level - unhighlight default entry
	else if (self.parentNode.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'ul')
		{
		lis = self.parentNode.getElementsByTagName('li');
		if (lis[0].className == 'hover3') lis[0].className = '';
		else lis[0].className = lis[0].className.replace(/ hover3/, '');
		}

	}
	
function unhighlight3(self)
	{
	var lis;
	
	// Highlighting stage 3: Leaving third level - highlight default entry
	if (self.parentNode.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'ul')
		{
		lis = self.parentNode.getElementsByTagName('li');
		if (lis[0].className.indexOf('hover3') == -1) lis[0].className = lis[0].className + ' hover3';
		}
	}

/* 
  Test to determine if listing impressions/clicks should be logged on this page
  -----------------------------------------------------------------------------
*/
function log_test()
	{
	// Don't log enquiry forms or localhost/LAN
	return (!window.location.href.match(/\-enquiry(\.php)?\?id=\d+/) && !window.location.href.match(/http\:\/\/(musicalchairs\.)?(dougal|localhost|192\.168\.1\.)/));
	}

/*
  Functions to run with window.onload
  -----------------------------------
*/

/* Assign functions to element events
 */
function assign2events()
	{
	// Select country automatically based on company selected by user.
	var selectCompany, selectCountry;
	selectCompany = document.getElementById('job_company');
	selectCountry = document.getElementById('job_country');
	if (selectCompany && selectCountry && selectCompany.tagName.toLowerCase() == 'select') selectCompany.onchange = function ()
		{
		selectCountry.disabled = true;
		selectCountry.value = '';
		rawRequest('ajax_php/get-company-countrycode.php', 'company='+this.value, selectJobCountry);
		}
		
	// Select expiry date automatically based on closing date as entered by user UNLESS expiry date has been edited manually.
	var inputJobEnd, inputJobExpiry, expiryEdited, expiryValue;
	inputJobEnd = document.getElementById('job_closing_date');
	inputJobExpiry = document.getElementById('job_expiry_date');
	expiryEdited = false;
	if (inputJobEnd && inputJobExpiry)
		{
		inputJobEnd.onblur = function ()
			{
			if (!expiryEdited) inputJobExpiry.value = inputJobEnd.value;
			}
		inputJobExpiry.onfocus = function ()
			{
			expiryValue = this.value;
			}
		inputJobExpiry.onblur = function ()
			{
			if (this.value != expiryValue) expiryEdited = true;
			}
		}
	}

// Bind to links:
//	1. Click logging function (sends ajax request to PHP script which updates db with click count)
//	2. Function to open some types of links in a new window/tab
//
// Modified 16/10/2010 to cope with links created by ajax requests that must (if internal links) open in the same 'popup' element.
//	- optional input popupDiv is the containing element of the ajax 'popup'.
//	- function should be called after ajax content is loaded into the 'popup'.
//
function links(popupDiv)
	{
	var as, i;

	function logClick(anchorTag)
		{
		if (log_test())
			{
			var trEl;
			trEl = closest(anchorTag, 'tr');

			if (trEl)
				{
				// jobID/courseID/etc is held as the id attribute of the <tr> of the listing, with "impression<code>" prefixed
				// 	e.g. <tr id="impressionjo2043"> for job listing with jobID = 2043
				trId = trEl.getAttribute('id');
				// Send Ajax request to log click
				if (trId && trId.match(/impression[a-z]{2}\d+/)) makeRequest('ajax_php/log-click.php', 'type='+trId.substr(10,2)+'&id='+trId.substr(12));
				}
			}

		return true; // <<<< ??? 
		}
	
	if (popupDiv) as = popupDiv.getElementsByTagName('a');
	else as = document.getElementsByTagName('a');
	
	for (i=0; i<as.length; ++i)
		{
		if ((as[i].hostname != window.location.hostname && as[i].protocol.toLowerCase().substr(0,4) == "http") || as[i].href.match(/\.(pdf|PDF)$/) || as[i].href.match(/\-pdf(\.php)?\?.+/))
			{
			// External links, PDFs
			// --------------------
			as[i].onclick = function () // log click and open in new tab/window if possible
				{
				logClick(this);
				if (window.open(this.href)) return false;
				else return true;
				};
			}
		
		else if (as[i].href.match(/(job\-advert|musician\-cv)(\.php)?(\?.*)?/))
			{
			// Rich text job adverts (internal) and musician CVs
			// -------------------------------------------------
			as[i].onclick = function()
				{
				logClick(this);
				if (window.open(this.href+(this.href.indexOf('?') == -1 ? '?' : '&')+'nw=1','advert',"status=no,toolbar=no,location=no,menubar=no,directories=no,resizable=yes,scrollbars=yes,width=734")) return false;
				else return true;
				};
			}

		else if (as[i].className.match(/delete-link/))
			{
			// Delete this entry?
			// ------------------
			as[i].onclick = function ()
				{
				var listingTr1, listingTr2;
				listingTr2 = closest(this, 'tr');

				listingTr1 = listingTr2;
				do
					{ // Find the previous <tr> (should contain the listing display)
					listingTr1 = listingTr1.previousSibling;
					if (!listingTr1) return true; // Past the first chiild !! Early Return !!
					} while (listingTr1 && listingTr1.nodeType != 1);
					
				// Highlight and ask the question
				listingTr1.className += (listingTr1.className ? " " : "") + "highlighted-row";
				if (confirm("Are you sure you wish to delete this listing?"))
					{
					rawRequest(this.href, '', function (responseText)
						{
						if (responseText == '1')
							{
							// If row 'deleted', then remove from display.
							listingTr1.parentNode.removeChild(listingTr1);
							listingTr2.parentNode.removeChild(listingTr2);
							}
						});
					return false;
					}
				else
					{
					// Unhighlight and cancel click
					listingTr1.className = listingTr1.className.replace("highlighted-row", "").replace("  ", " ");
					return false;
					}
				};
			}

		else if (as[i].className.match(/\bprint\b/))
			{
			// Print invoice
			// -------------
			as[i].onclick = function ()
				{
				var drsEl;
				drsEl = closest(this, 'div', 'drsElement');
				if (drsEl) window.open(windows[drsEl.winId].href + '&print=now');
				else window.print();
				return false;
				};
			}

		else 
			{
			// Other internal links
			// --------------------
			as[i].onclick = function()
				{
				// log click and continue (same window).
				// Preserve &nw query string parameter if present.
				// Load into ajax div if in a 'popup' div already.
				var divs, i, els, j, maxWidth, popupHref;
	
				logClick(this);

				if (popupDiv)
					{
					divs = popupDiv.getElementsByTagName('div');
					for (i=0; i<divs.length; ++i)
						{
						if (divs[i].className == 'drsContent')
							{
							makeRequest(popupHref = this.href, 'ajax=1', divs[i], function ()
								{
								popupDiv.id += '_'; // Decouple the element from its original link, so subsequent clicks on the original link will open another window.
					
								refreshFns();
					
								// Size width of popup to contain content
								windows[popupDiv.winId].resizeToFit(getElements('drsContent', 'div', popupDiv.id)[0]);
								windows[popupDiv.winId].href = popupHref;
								});
							return false; // !! Early Return !!
							}
						}
					}
	
				// If not an ajax 'popup' or failed to find ajax content div, continue as normal...
	
				if (window.location.href.match(/[?&]nw\=1/))
					{
					// Preserve separate new window flag (no header, menus or footer)
					window.location.href = this.href+(this.href.indexOf('?') == -1 ? '?' : '&')+'nw=1';
					return false;
					}
				else
					{
					// Normal link
					return true;
					}
				};
			}
		}
	}

// Ensure error messages are obvious by scrolling to the first one found.
function errorScroll ()
	{
	var ps, i;
	ps = document.getElementsByTagName('p');
	for (i=0; i<ps.length; ++i)
		{
		if (ps[i].className.match(/\berror\b/))
			{
			ps[i].scrollIntoView();
			return;
			}
		}
	}

// JS input character countdown for inputs/textareas that have a
// restriction on the available number of characters.
function inputCountDown()
	{
	var textareas, inputs, i, maxlen;
	inputs = document.getElementsByTagName('input');
	for (i=0; i<inputs.length; ++i)
		{
		if (maxlen = inputs[i].getAttribute('maxlength')) 
			{
			inputs[i].onkeyup = function ()
				{
				if (counter = document.getElementById(this.getAttribute('id')+'-counter')) counter.innerHTML = this.getAttribute('maxlength') - this.value.length;
				};
			}
		}
	textareas = document.getElementsByTagName('textarea');
	for (i=0; i<textareas.length; ++i)
		{
		if (maxlen = textareas[i].maxlength)
			{
			textareas[i].onkeyup = function ()
				{
				if (counter = document.getElementById(this.getAttribute('id')+'-counter')) counter.innerHTML = this.maxlength - this.value.length;
				};
			}
		}
	}

// Focus on first form input
//
function setFocus()
	{
	var inputs, i;
	inputs = document.getElementsByTagName('input');
	for (i=0; i<inputs.length; ++i)
		{
		if (inputs[i].getAttribute('type') != 'hidden')
			{
			inputs[i].focus();
			break;
			}
		}
	}
	
// Sub type/Category selections on Publish/Add pages
//	- make label text black if checkbox checked.
function subtypeSelection()
	{
	var fieldsets, inputs, i, j, label;
	
	fieldsets = document.getElementsByTagName('fieldset');
	for (i=0; i < fieldsets.length; ++i)
		{
		if (fieldsets[i].className == 'add-sub-categories')
			{
			inputs = fieldsets[i].getElementsByTagName('input');
			for (j=0; j < inputs.length; ++j)
				{
				inputs[j].onclick = function ()
					{
					label = this.parentNode;
					if (this.parentNode.tagName.toLowerCase() == 'label')
						{
						if (this.checked) label.style.color = '#000000';
						else if (label.getAttribute('style')) label.removeAttribute('style');
						}
					
					adjustPrice(this);
					}
				}
			}
		}
	}
	
function layout()
	{
	// Stretch maincontainer to match RH sidebar
	//
	var main, side;
	main = document.getElementById('main_container');
	side = document.getElementById('side_container');
	if (main && side && side.offsetHeight + side.offsetTop > main.offsetHeight)
		{
		if (ieversion == null || ieversion > 6) main.style.minHeight = (side.offsetHeight + side.offsetTop).toString().concat('px');
		else main.style.height = (side.offsetHeight + side.offsetTop).toString().concat('px');
		}
	}
	
/* Log page impressions. Sends AJAX request to PHP script which updates db with impression count.
 */
function impressionLogger()
	{
	var trs, i, trId, ids_query_string, type;

	if (log_test())
		{
		ids_query_string = '';
		trs = document.getElementsByTagName('tr');
		for (i=0; i < trs.length; ++i)
			{
			// jobID/courseID/etc is held as the id attribute of the <tr> of the listing, with "impression<code>" prefixed
			// 	e.g. <tr id="impressionjo2043"> for job listing with jobID = 2043
			trId = trs[i].getAttribute('id');
			if (trId && trId.substr(0,10) == 'impression')
				{
				type = trId.substr(10,2)
				ids_query_string += '&ids[]='+trId.substr(12);
				}
			}

		makeRequest('ajax_php/log-impression.php', 'type='+type+ids_query_string);
		}
	}

/* Show Javascript only elements
 */
function showJS()
	{
	var els, i;
	els = document.getElementsByTagName("*");
	for (i=0; i<els.length; ++i) if (els[i].className.match(/\bJS\b/)) els[i].className = trim(els[i].className.replace("JS", "").replace("  ", " "));
	}
	
/*	Automatic dropdown form triggers - for e.g. sorting on job results
 *
 * 	Ensures that the select's onchange sends user straight to the newly sorted/filtered/whatever page.
 * 	Also hides the submit button.
 *
 *	The <select> should have a name and id that is dropdownName, and should be within a <fieldset>/<div>/whatever so that its grandparent is the <form> element.
 *	The action of the <form> element should be relative to the site root (base_href is set in loadFns())
 *	The submit button <input> should have an id that is dropdownName-submit
 */
function dropdownAuto (dropdownName)
	{
	var input, select;
	input = document.getElementById(dropdownName+'-submit');
	if (input)
		{
		select = document.getElementById(dropdownName);
		select.onchange = function ()
			{
			var href, separator, qmPos, hrefQueryString, queryStringRegexp;
			
			separator = '?';
			href = select.parentNode.parentNode.getAttribute('action');
			if (href.substr(0, base_href.length) != base_href) href = base_href + href;
			
			// Preserve current query string for next load of the page (but remove any old parameter for this form)
			qmPos = window.location.href.indexOf('?');
			if (qmPos != -1)
				{
				queryStringRegexp = new RegExp("(\\?|\\&)"+dropdownName+"\\=[^&]*", "g");
				hrefQueryString = window.location.href.substr(qmPos).replace(queryStringRegexp, '');
				if (hrefQueryString.length)
					{
					href += '?'+ hrefQueryString.substr(1);
					separator = '&';
					}
				}
			
			// New page
			window.location.href = href + separator + dropdownName + '=' + this.value;
			}
		input.style.position = 'absolute';
		input.style.left = '-5000px';
		input.style.width = '8em'; // IE7
		}
	}
	
/* 
 * Highlight table row jumped to by page anchor in URL
 */
function highlightAnchor()
	{
	if (window.location.hash.length > 1)
		{
		var el;
		el = document.getElementById(window.location.hash.substr(1));
		el.className += 'highlighted-row';
		el.scrollIntoView();
		window.scrollBy(0,-10);
		}
	}

/*
  Print window if signalled in query string
*/
function printnow()
	{
	if (window.location.href.match(/(\?|\&)print\=now/)) window.print();
	}

var ieversion, base_href; // Hold base href globally for IE's benefit

function loadFns () 	// Functions to run at window.onload
	{		// ---------------------------------
	// Test for IE
	// -----------
	if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) //test for MSIE x.x;
		ieversion=new Number(RegExp.$1);
	else
		ieversion = null;

	// base href for IE
	// ----------------
	base = document.getElementsByTagName('base');
	if (base && base[0] && base[0].href) base_href = base[0].href;
	else base_href = 'http://'+document.domain+'/';

	// Javascript notice for *-add pages
	jNotice = document.getElementById('javascript-notice');
	if (jNotice) jNotice.parentNode.removeChild(jNotice);

	// Priority to event binding functions
	assign2events();
	subtypeSelection();
	links();
	inputCountDown();

	// Next the layout and appearance changing functions
	layout();
	setFocus();
	errorScroll();
	dropdownAuto('sort');
	dropdownAuto('month-year');
	
	// Lastly non-urgent functions (relative to page load time)
	impressionLogger();
	showJS();
	highlightAnchor();
	printnow();
	}
	
function refreshFns ()	// Selected functions to run after *significant* ajax changes to the page (may need revision in the future)
	{			// ----------------------------------------------------------------------
	assign2events();
	subtypeSelection();
	links();
	inputCountDown();

	layout();
	dropdownAuto('sort');
	dropdownAuto('month-year');

	showJS();
	}
	
if (window.addEventListener) // DOM Level 2 API
	window.addEventListener("load", loadFns, 0);
else if (window.attachEvent) // IE workaround
	window.attachEvent("onload", loadFns);

//* Verify Forms */
//---------------//

function checkAddGeneric(section, dateCheck)
	{
	function mandatory_date(n)
		{
		x=n.parentNode.firstChild;
		while (x.nodeType!=1) x=x.nextSibling;
		if (x.innerHTML.match(/\(optional\)/)) return false;
		else return true;
		}

	var el, el2;
	
	el = document.getElementById(section+'_name');
	if (el && trim(el.value) == "")
		{
		alert("Please provide a "+section+" name");
		el.focus();
		return false;
		}
	
	el = document.getElementById(section+'_email');
	if (el)
		{
		if (trim(el.value) == "")
			{
			alert("Please provide a "+section+" email");
			el.focus();
			return false;
			}
		if (!isValidEmail(el.value))
			{
			alert("Your email address is not valid");
			el.focus();
			return false;
			}
		el2 = document.getElementById(section+'_email_confirm');
		if (el2)
			{
			if (el.value != el2.value)
				{
				alert("Email and confirm email do not match");
				el.focus();
				return false;
				}
			}
		}
	
	el = document.getElementById(section+'_towncity');
	if (el && trim(el.value) == "")
		{
	        alert("Please provide a "+section+" town/city");
        	el.focus();
		return false;
		}

	el = document.getElementById(section+'_country');
	if (el && el.value == "")
		{
	        alert("Please select a country");
        	el.focus();
		return false;
		}		
	
	el = document.getElementById(section+'_description');
	if (el && trim(el.value) == "")
		{
	        alert("Please provide a "+section+" description");
        	el.focus();
		return false;
		}

	el = document.getElementById(section+'_start');
	if (el && trim(el.value) == "" && mandatory_date(el))
		{
		alert("Please provide a "+section+" start date");
		document.getElementById(section+'_start-picker-button').click();
		document.getElementById('datepicker').scrollIntoView();
		return false;
		}		

	el = document.getElementById(section+'_end');
	if (el && trim(el.value) == "" && mandatory_date(el))
		{
		alert("Please provide a "+section+" end date");
		document.getElementById(section+'_end-picker-button').click();
	       	document.getElementById('datepicker').scrollIntoView();
		return false;
		}
	
	return true;
	}
	
function checkAddCourse()
	{
	if (!checkAddGeneric('course')) return false;

	// Check for Disciplines
	if (disciplineCount < 1)
		{
		alert("Please select at least one disipline");	
		document.advert_add.elements[0].focus();
		return false;
		}

	return true;
	}

function checkAddCompetition()
	{
	if (!checkAddGeneric('competition')) return false;

	// Check for Disciplines
	if (disciplineCount < 1)
		{
		alert("Please select at least one disipline");	
		document.advert_add.elements[0].focus();
		return false;
		}

	return true;
	}

function checkAddSale()
	{
	var el;
	
	if (!checkAddGeneric('sale')) return false;
	
	el = document.getElementById('sale_subtype');
	if (el && el.value == "")
		{
	        alert("Please provide an instrument family");
        	el.focus();
	        return false;
		}

	el = document.getElementById('sale_currency');
	if (trim(el && el.value) == "")
		{
		alert("Please select a currency");
        	el.focus();
		return false;
		}

	el = document.getElementById('sale_value');
	if (el && trim(el.value) == "")
		{
	        alert("Please provide a price");
        	el.focus();
		return false;
		}

	return true;
	}

function checkAddJob()
	{
	var el, inputs, i, flag;
	
	if (!checkAddGeneric('job')) return false;

	el = document.getElementById('job_company');
    	if (el && trim(el.value) == "")
		{
	        alert("Please provide an orchestra/company name");
        	el.focus();
		return false;
		}

	flag = false;
	el = null;
	inputs = document.getElementsByTagName('input');
	for (i=0; i<inputs.length; ++i)
		{
		if (inputs[i].getAttribute('name') == 'job_category')
			{
			if (!el) el = inputs[i];
			if (inputs[i].checked)
				{
				flag = true;
				break;
				}
			}
		}
	if (!flag)
		{
		alert("Please select a job category")
		el.focus();
		return false;
		}

	el = document.getElementById('job_type');
    	if (el && trim(el.value) == "")
		{
	        alert("Please select a job type");
        	el.focus();
		return false;
		}
		
	if (document.getElementById('job_info_url').checked)
		{
		el = document.getElementById('job_website');
		if (el && trim(el.value) == "")
			{
			alert("Please provide a website link");
			el.focus();
			return false;			
			}
		}
	
	if (document.getElementById('job_info_pdf').checked)
		{
		el = document.getElementById('job_pdf');
		if (el && trim(el.value) == "" && !el.className.match(/\buploaded\b/))
			{
			alert("Please upload a PDF file");
			el.focus();
			return false;			
			}
		}

	el = document.getElementById('job_subtype');
    	if (el && trim(el.value) == "")
		{
	        alert("Please select a job discipline");
        	el.focus();
		return false;
		}

	return true;
	}

function checkManagerLogin()
	{
	var el;
	
	if (trim(el = document.getElementById('login_email').value) == "")
		{
	        alert("Please provide your email");
        	el.focus();
	        return false;
	        }
	
	el = document.getElementById('login_password');
	if (el && trim(el.value) == "")
		{
	        alert("Please provide your password");
        	el.focus();
	        return false;
	        }
	
	else return true;
	}

function checkAddAccount()
	{
	// Check Job account details
	if (document.advert_add.subscription_name && trim(document.advert_add.subscription_name.value) == "")
		{
		alert("Please enter a login manager name");
		document.advert_add.subscription_name.focus();
		return false;
		}
		
	if (document.advert_add.subscription_email)
		{	
		if (trim(document.advert_add.subscription_email.value) == "")
			{
			alert("Please enter a login manager email address");
			document.advert_add.subscription_email.focus();
			return false;
			}
		
		if (!isValidEmail(trim(document.advert_add.subscription_email.value)))
			{
			alert("Please check your email address - it appears to be invalid.");
			document.advert_add.subscription_email.focus();
			return false;
			}

		if (document.advert_add.subscription_email.value != document.advert_add.subscription_email2.value)
			{
			alert("Email and confirm email do not match");
			document.advert_add.subscription_email.focus();
			return false;
			}
		}

	if (document.advert_add.subscription_password)
		{
		var subscriptionPassword = document.advert_add.subscription_password.value;
		if (subscriptionPassword.length < 6 || subscriptionPassword.length > 15)
			{
			alert("Please enter a password between 6 and 15 characters long");
			document.advert_add.subscription_password.focus();
			return false;
			}
		}

	return true;
	}	

function checkAddMusician()
	{
	var el;
	
	el = document.getElementById('musician_firstname');
	if (el && trim(el.value) == "")
		{
		alert("Please enter a firstname");
		el.focus();
		return false;
		}
	
	el = document.getElementById('musician_surname');
	if (el && trim(el.value) == "")
		{
		alert("Please enter a surname");
		el.focus();
		return false;
		}

	el = document.getElementById('musician_email');
	if (el)
		{
		if (trim(el.value) == "")
			{
			alert("Please enter an email address");
			el.focus();
			return false;
			}
			
		if (el.value != document.getElementById('musician_email_confirm').value)
			{
			alert("Email and confirm email do not match");
			el.focus();
			return false;
			}
		}

	el = document.getElementById('musician_subtype');
	if (el && el.value == "")
		{
		alert("Please select a discipline");
		el.focus();
		return false;
		}

	el = document.getElementById('musician_country');
	if (el && el.value == "")
		{
		alert("Please select a country");
		el.focus();
		return false;
		}
	}

function checkAddInvoice()
	{
	var el;
	
 	if (trim(document.advert_add.invoice_name.value) == "")
		{
		alert("Please provide an invoice name");
		document.advert_add.invoice_name.focus();
	        return false;
		}
	
	el = document.advert_add.invoice_position;
	if (el && trim(el.value) == "")
		{
		alert("Please provide an invoice position");
		document.advert_add.invoice_position.focus();
		return false;
		}	
	
	if (trim(document.advert_add.invoice_phone.value) == "")
		{
		alert("Please provide an invoice phone number");
		document.advert_add.invoice_phone.focus();
		return false;
		}
	
	if (trim(document.advert_add.invoice_email.value) == "")
		{
		alert("Please provide an invoice email");
		document.advert_add.invoice_email.focus();
		return false;
		}
	if (document.advert_add.invoice_email.value != document.advert_add.invoice_email_confirm.value)
		{
		alert("Invoice email and confirm email do not match");
		document.advert_add.invoice_email.focus();
		return false;
		}		
	
	if (!isValidEmail(document.advert_add.invoice_email.value))
		{
		alert("Your invoice email address is not valid");
		document.advert_add.invoice_email.focus();
		return false;		
		}	
	
	if (trim(document.advert_add.invoice_address_1.value) == "")
		{
		alert("Please provide a first line of address");
		document.advert_add.invoice_address_1.focus();
		return false;
		}	
	
	if (document.advert_add.invoice_country.value == 'gb' && trim(document.advert_add.invoice_postcode.value) == "")
		{
		alert("Please provide an invoice postcode");
		document.advert_add.invoice_postcode.focus();
		return false;
		}
	
	if (trim(document.advert_add.invoice_country.value) == "")
		{
		alert("Please provide a country");
		document.advert_add.invoice_country.focus();
		return false;
		}

	if(trim(document.advert_add.invoice_vatnum.value) != "")
		{
		if (!checkVATNumber(trim(document.advert_add.invoice_vatnum.value)))
			{
			alert("Your VAT number does not appear to be valid");	
			document.advert_add.invoice_vatnum.focus();
			return false;				
			}
		}

	return true;
	}

