/* --- JavaScript --- */
/* ---- main.js ----- */

/* ============== */
/* === EVENTS === */
/* ============== */

/* === addEvent/removeEvent written by Dean Edwards (2005) with input from Tino Zijdel, Matthias Miller, Diego Perini: http://dean.edwards.name/weblog/2005/10/add-event/ === */
function addEvent( element, type, handler ) {
	if ( !element ) element = window;	// fix: sometimes element does not seem to exist, even though one is passed
	if ( element.addEventListener ) {
		element.addEventListener( type, handler, false );
	} else {
		// assign each event handler a unique ID
		if ( !handler.$$guid ) handler.$$guid = addEvent.guid++;
		// create a hash table of event types for the element
		if ( !element.events ) element.events = {};
		// create a hash table of event handlers for each element/event pair
		var handlers = element.events[ type ];
		if ( !handlers ) {
			handlers = element.events[ type ] = {};
			// store the existing event handler (if there is one)
			if ( element[ "on" + type ] ) {
				handlers[ 0 ] = element[ "on" + type ];
			}
		}
		// store the event handler in the hash table
		handlers[ handler.$$guid ] = handler;
		// assign a global event handler to do all the work
		element[ "on" + type ] = handleEvent;
	}
};
// a counter used to create unique IDs
addEvent.guid = 1;

function removeEvent(element, type, handler) {
	if ( element.removeEventListener ) {
		element.removeEventListener( type, handler, false );
	} else {
		// delete the event handler from the hash table
		if ( element.events && element.events[ type ] ) {
			delete element.events[ type ][ handler.$$guid ];
		}
	}
};

function handleEvent( event ) {
	var returnValue = true;
	// grab the event object (IE uses a global event object)
	event = event || fixEvent( (( this.ownerDocument || this.document || this ).parentWindow || window ).event );
	// get a reference to the hash table of event handlers
	var handlers = this.events[ event.type ];
	// execute each event handler
	for ( var i in handlers ) {
		this.$$handleEvent = handlers[ i ];
		if ( this.$$handleEvent( event ) === false ) {
			returnValue = false;
		}
	}
	return returnValue;
};

function fixEvent( event ) {
	// add W3C standard event methods
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
};
fixEvent.preventDefault = function() {
	this.returnValue = false;
};
fixEvent.stopPropagation = function() {
	this.cancelBubble = true;
};
/* --- /addEvent/removeEvent --- */

function stopDefault( e ) {
	if ( e && e.preventDefault ) e.preventDefault();	// Prevent default browser action (W3C)
	else window.event.returnValue = false;					// IE version
	return false;
}

function normEvent( e ) {
	e = e || window.event;
	if ( !e.target ) e.target = e.srcElement;
	return e;
}

/* =============== */
/* === PRELOAD === */
/* =============== */

function preloadImage(src) {
	if ( !document.images ) return null;
	var img = new Image();
	img.src = src;
	return img.src;
}

/* =========== */
/* === BOM === */
/* =========== */

function queryString( q ) {
	var queryObj = {};
	var qString = window.location.search.substring( 1 );
	var qArray = qString.split( "&" );
	for ( var a = 0; a < qArray.length; a++ ) {
		var keyValue = qArray[ a ].split( "=" );
		queryObj[ keyValue[ 0 ] ] = keyValue[ 1 ] || "";	// fall back to empty string if no value is defined
	}
	if ( q && q.constructor == String ) return queryObj[ q ];
	else return queryObj;
}

/* =========== */
/* === DOM === */
/* =========== */

function domReady( f ) {
	if ( domReady.done ) return f();							// If DOM is already loaded, execute the function right away
	
	if ( domReady.timer ) {										// If wwe've already added a function
		domReady.ready.push( f );								// Add it to the list of functions to execute
	} else {
		addEvent( window, "load", isDOMReady );			// Attach an event for when the page finishes loading, just in case it finishes first.
		domReady.ready = [ f ];									// Initialize the array of functions to execute;
		domReady.timer = setInterval( isDOMReady, 13 );	// Check to see if the DOM is ready as quickly as possible
	}
}

function isDOMReady() {																										// Checks to see if the DOM is ready for navigation
	if ( domReady.done ) return false;																					// If we already figures out that the page is ready, ignore
	
	if ( document && document.getElementsByTagName && document.getElementById && document.body ) {	// Check to see if a number of functions and elements are able to be accessed
		clearInterval( domReady.timer );																					// If they're ready, we can stop checking
		domReady.timer = null;
		
		for ( var i = 0; i < domReady.ready.length; i++ ) domReady.ready[ i ]();							// Execute all functions that were waiting	
		domReady.ready = null;
		domReady.done = true;
	}
}

/* --- nodes --- */

function create( elem ) {
	return document.createElementNS ? document.createElementNS( 'http://www.w3.org/1999/xhtml', elem ) : document.createElement( elem );
}

function before( parent, before, elem ) {
	if ( elem == null ) {										// Check to see if no parent was provided
		elem = before;
		before = parent;
		parent = before.parentNode;
	}
	parent.insertBefore( checkElem( elem ), before );
}

function append( parent, elem ) {
	parent.appendChild( checkElem( elem ));
}

function checkElem( elem ) {
	return elem && elem.constructor == String ? document.createTextNode( elem ) : elem;	// if a string was provided, convert it into a text node
}

function remove( elem ) {
	if ( elem ) elem.parentNode.removeChild( elem );
}

function empty( elem ) {
	while ( elem.firstChild ) remove( elem.firstChild );
}

/* --- finding elements --- */
function id( name ) {
	return document.getElementById( name );	// -> HTML element
};

	/* === fix document.getElementById for IE - based on code by J. Max Wilson: http://www.sixteensmallstones.org/ie-javascript-bugs-overriding-internet-explorers-documentgetelementbyid-to-be-w3c-compliant-exposes-an-additional-bug-in-getattributes === */ 
	document.nativeGetElementById = document.getElementById;
	document.getElementById = function( id ) {
	    if ( document.all ) {   // only override when document.all is supported (IE + Opera)
	
	        document.getElementById = function( id ) {
	            var elem = document.nativeGetElementById( id );
	            if ( !elem ) return null;
	            if ( elem.attributes['id'] && elem.attributes['id'].value == id ) return elem;							// make sure that it is a valid match on id
	
	            for ( var i = 1; i < document.all[ id ].length; i++ ) {															// otherwise find the correct element
	                if ( document.all[ id ][ i ].attributes[ 'id' ].value == id ) return document.all[ id ][ i ];
	            }
	        };
	    } else {    // otherwise change back to original
	        document.getElementById = document.nativeGetElementById;
	        document.nativeGetElementById = null;  																						// we don't need it anymore
	    }
	};
	document.getElementById();																													// run document.getElementById() once to let it rewrite itself
	/* --- /fix document.getElementById for IE --- */

function tag( name, elem ) {
	return ( elem || document ).getElementsByTagName( name );	// -> Array
};

function withClass( name, sel, sel2 ) {														// sel and sel2 are both optional and can be either an element or a tag (one of each)
	var haveClass = [];
	var regExp = new RegExp( "(^|\\s)" + name + "(\\s|$)" );								// allows for multiple class names
	var tagName = sel.constructor == String ? sel : sel2;
	var elem = sel.constructor == String ? sel2 : sel;
	var elements = ( elem || document).getElementsByTagName( tagName || "*" );		// use document if no element has been specified and get all elements if no tag name has been specified
	for ( var e = 0; e < elements.length; e++) {
		var element = elements[ e ];
		if ( hasClass( element, name )) haveClass[ haveClass.length ] = element;
	}
	return haveClass;																					// -> Array
};

function hasClass( elem, name ) {
	if ( !name && elem.className != "") return true;			// if no className has been specified any className will do | -> Boolean
	var regExp = new RegExp( "(^|\\s)" + name + "(\\s|$)" );	// allows for multiple class names
	if ( regExp.test( elem.className )) return true;			// -> Boolean
	return false;															// -> Boolean
};

function prev( elem ) {
	do {
		elem = elem.previousSibling;
	} while ( elem && elem.nodeType != 1 );
	return elem;
}

function next( elem ) {
	do {
		elem = elem.nextSibling;
	} while ( elem && elem.nodeType != 1 );
	return elem;
}

function first( elem ) {
	elem = elem.firstChild;
	return elem && elem.nodeType != 1 ? next( elem ) : elem;
}

function last( elem ) {
	elem = elem.lastChild;
	return elem && elem.nodeType != 1 ? next( elem ) : elem;
}


/* --- get/set attributes --- */
function attr( elem, attrib ) {															// attrib can be a String (get) or an Object (set)
	if ( attrib.constructor == String ) {
		name = validName( attrib );
		return elem[ name ] || elem.getAttribute( name ) || '';					// -> String (attribute value)
	}
	else if ( attrib.constructor == Object ) {
		for ( n in attrib ) {
			var value = attrib[ n ];
			name = validName( n );
			if ( name == "className" || name == "rel" || name == "rev" ) {
				addToAttr( elem, name, value );
			} else {
				elem[ name ] = value;														// do it quick if possible
				if ( elem.setAttribute ) elem.setAttribute( name, value );		// XML fallback
			}
		}
		return true;																			// -> Boolean (values are set)
	}
	function validName( name ) {
		return { 'for': 'htmlFor', 'class': 'className' }[ name ] || name;	// rename in case of 'for' or 'class' attribute
	};
	return '';																					// -> String (empty: attrib was neither a String or Object)
};

function addClass( elem, name ) {
	addToAttr( elem, "className", name );
}

function removeClass( elem, name ) {
	removeFromAttr( elem, "className", name );
}

function addToAttr( elem, attr, value ) {	// can be used for class, rel and rev attributes
	removeFromAttr( elem, attr, value );	// make sure there won't be any doubles
	elem[ attr ] += " " + value;
}

function removeFromAttr( elem, attr, value ) {									// can be used for class, rel and rev attributes
	var remain = [];
	var values = elem[ attr ].split(/\s+/);										// seperate class names (devided by one or more whitespaces)
	for ( var v = 0; v < values.length; v++ ) {
		if ( values[ v ] != value ) remain[ remain.length ] = values[ v ];
	}
	elem[ attr ] = remain.join( " " );
}

/* ============= */
/* === STYLE === */
/* ============= */

/* --- check for CSS support --- */
function cssSupport() {
	if ( !document.styleSheets ) return false;									// styleSheets object is not supported
	var css = document.styleSheets;
	for ( var s = 0; s < css.length; s++) {
		if ( s == 0 ) {
			if ( !( css[ 0 ].cssRules || css[ 0 ].rules )) return false;	// both methods (cssRules/rules) are not supported
		}
		if ( !css[ s ].disabled ) return true;										// at least one of the stylesheets is not disabled
	}
	return false;																			// stylesheets are all disabled or not supported at all
}


/* ================================== */
/* ============= CUSTOM ============= */
/* ================================== */


////////// ADD JS BUTTONS //////////

function addJSbuttons() {
	addJSfavorites();
}

function addJSfavorites() {
	var pageTools = id( "pageTools" );
	var favTitle = window.document.title || "Schouten Training";	// fall back
	var favUrl = window.location.href;
	if ( !pageTools || !favUrl || ( favUrl.toLowerCase().indexOf( "file://" ) == 0 || favUrl.toLowerCase().indexOf( "javascript:" ) == 0 ) ) return;	// doesn't work if url starts with "file://" or "javascript:"
	
	var toolsMenu = tag( "ul", pageTools )[ 0 ];
	if ( !toolsMenu ) return;
	
	var favLabel = languageObj.addToFavorites || "add to favorites";	// fall back to English if not defined
	
	var toolItem = create( "li" );
	var addLink = create( "a" );
	addLink.href = "#";
	addLink.favTitle = favTitle;
	addLink.favUrl = favUrl;
	append( addLink, favLabel );
	append( toolItem, addLink );
	append( toolsMenu, toolItem );
	
	if ( window.opera ) {	// Opera
		addLink.rel = "sidebar";
	} else if ( window.sidebar ) {	// Mozilla Firefox Bookmark
		addEvent( addLink, "click", function( e ) {
			window.sidebar.addPanel( this.favTitle, this.favUrl, "" );	// gives error on local files
			return stopDefault( e );
		} );
	} else if( window.external ) { // IE Favorite
		addEvent( addLink, "click", function( e ) {
			window.external.AddFavorite( this.favUrl, this.favTitle );
			return stopDefault( e );
		} );
	}
}


///////////// TOP VISUAL /////////////

function initTopVisual() {
	var view = 10000;			// time between transitions in milliseconds (integer)
	var transition = 2500;	// duration of transition in milliseconds (integer)
	var frame = 50;			// duration of each transition frame in milliseconds (integer >= 50)
	
	// don not change code below //
	var fadeSteps = [];
	window.currentTopVisual = "base";
	
	var topVisualArr = window.topVisualArr || [];
	var numOfImages = topVisualArr.length;
	
	var siteHeader = id( "siteHeader" );
	var topVisual = id( "topVisual" );
	if ( !siteHeader || !topVisual || numOfImages == 0 ) return;
	
	setOpacity( 0 );
	topVisual.style.display = "block";
	
	var bgHeader = siteHeader.style.backgroundImage;
	if ( bgHeader ) {
		var delay = true;
		var startChar = '(';
		var endChar = ')';
		if ( window.opera ) startChar = endChar = '"';	// Opera uses url("...") notation instead of url(...)
		bgHeader = siteHeader.style.backgroundImage = "url(" + preloadImage( bgHeader.substring( bgHeader.indexOf( startChar ) + 1, bgHeader.lastIndexOf( endChar ) ) ) + ")";	// preload default image
	}
	
	for ( var i = 0; i < numOfImages; i++ ) {
		topVisualArr[ i ] = "url(" + preloadImage( topVisualArr[ i ] ) + ")";	// preload images
		if ( bgHeader && topVisualArr[ i ] == bgHeader ) var defInArray = i;	// check if default image is already in array
	}
	if ( !defInArray && defInArray !== 0 ) topVisualArr[ numOfImages ] = bgHeader;	// add default image to array if it's not in yet
	
	var frames = transition / frame;
	var opacityStep = Math.round( 100 / frames );
	
	if ( delay ) {
		setInterval( animVisual, view + transition )
	} else {
		animVisual();
		setInterval( animVisual, view + transition )
	}
	
	function animVisual() {
		// fade in or out
		if ( window.currentTopVisual == "base" ) {
			var fromElm = siteHeader;
			var toElm = topVisual;
			var start = 0;
			window.currentTopVisual = "top";
		} else {
			var fromElm = topVisual;
			var toElm = siteHeader;
			var start = 100;
			window.currentTopVisual = "base";
		}
		
		// get random image, other that the current one
		var currentVisual = fromElm.style.backgroundImage;
		do {
			var newVisual = topVisualArr[ Math.round( (topVisualArr.length - 1) * Math.random() ) ];
		} while ( newVisual == currentVisual );
		toElm.style.backgroundImage = newVisual;
		//alert(newVisual);
		// clear previous fade steps
		for ( var f = 0; f < fadeSteps.length; f++ ) {
			clearTimeout( fadeSteps[ f ] );
		}
		
		// calculate fade
		var step = 0;
		do {
			var deviation = Math.sin( 2 * Math.PI / frames * ( step + 1 ) ) * -1 * opacityStep;	// deviation that creates an animation curve, set acceleration to 0 for linear animation
			var opacity = Math.round( opacityStep * ( step + 1 ) + deviation );
			
			if ( step >= frames || opacity > 100 ) opacity = 100;
			
			fadeSteps[ step ] = setTimeout( "setOpacity( " + Math.abs( start - opacity ) + ")", frame * step );
			step++;
		} while ( step < frames && opacity < 100 );
	}
}

function setOpacity( value ) {
    //alert(value);
	var topVisual = id( "topVisual" );
	if ( topVisual ) {
		topVisual.style.opacity = value / 100;	// W3C
		if ( document.all && !window.opera ) topVisual.style.filter = "alpha(opacity=" + value + ")";	// IE
	}
}


/* --- call functions only if the used methods are supported --- */
domReady( function() {

	if ( !languageObj ) languageObj = {};
	
	if ( cssSupport() ) {
		initTopVisual();
		addJSbuttons();
	}
});

domReady(function() {
    var allHeight = document.getElementById('allButFooter').clientHeight;
    document.getElementById('footer').style.top = allHeight + 'px';
});

