function addWindowOnLoadEvent(func , domElementId)
{
	// config
	var checkInterval = 250; //ms to check to see if elements have loaded
	
	// see if we have the function array otherwise create it
	if (typeof FUTURE_ONLOAD_FUNCTIONS != 'object')
	{
		//if(window.console)window.console.log('create array and empty timer');
		FUTURE_ONLOAD_FUNCTIONS = new Array();
		FUTURE_DOM_CHECK_TIMER  = false;
	}
	// get  function params
	var func = func;
	var domElementId = (domElementId)?domElementId:false;
	
	// package the function and dom element id
	var functionCall = Array(func , domElementId);
	
	// pack into the global array
	FUTURE_ONLOAD_FUNCTIONS.push(functionCall);
	
	if(!FUTURE_DOM_CHECK_TIMER  && (functionCall[1] != false)) // if we have a call to a dom element
	{
		// create a new timer
		//if(window.console)window.console.log('create a timer - started by ' + functionCall[1]);
		FUTURE_DOM_CHECK_TIMER = setInterval(
			function()
			{
				//if(window.console)window.console.log('timer called');
				//  loop around the FUTURE_ONLOAD_FUNCTIONS and if it has a element_id check to see if its loaded
				var nr = FUTURE_ONLOAD_FUNCTIONS.length -1;
				for(var i = nr; i > -1; i--)
				{
					if ((typeof FUTURE_ONLOAD_FUNCTIONS[i][0] == 'function') && FUTURE_ONLOAD_FUNCTIONS[i][1] && document.getElementById(FUTURE_ONLOAD_FUNCTIONS[i][1]))
					{
						FUTURE_ONLOAD_FUNCTIONS[i][0].call();
						//if(window.console)window.console.log( 'timer called: ' + FUTURE_ONLOAD_FUNCTIONS[i][1] );
						FUTURE_ONLOAD_FUNCTIONS[i] = false;
					}	
				}
				
			} , checkInterval
		);
	}
}

function callWindowOnLoadFunctions()
{
	if(FUTURE_DOM_CHECK_TIMER)clearInterval(FUTURE_DOM_CHECK_TIMER);
	//if(window.console)window.console.log('FUTURE_DOM_CHECK_TIMER killed ');
	var nr = FUTURE_ONLOAD_FUNCTIONS.length -1;
	for(var i = nr; i > -1; i--)
	{
		if (typeof FUTURE_ONLOAD_FUNCTIONS[i][0] == 'function')
		{
			//if(window.console)window.console.log('window onload called: ' + i);
			FUTURE_ONLOAD_FUNCTIONS[i][0].call();
		}	
	}
}

function getParamFromURL( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

/***
 * Function: setupPrintLinks
 * Grabs all the <a>s with a class of "print" and sticks an onclick event on them
 * which triggers printing and prevents the link from being followed.
 ***/
function setupPrintLinks()
{
	var allLinks = document.getElementsByTagName("a");
	for (i=0; i<allLinks.length; i++)
	{
		var theClass = allLinks[i].className;
		if (theClass == "print")
		{
			allLinks[i].onclick = function(){
				window.print();
				return false;
			}
		}
	}
}
addWindowOnLoadEvent(setupPrintLinks);

/*function setupAnimateBlogLogos()
{
	if ($('network_links') != null)
	{
		var animBlogs = new logoAnim();
		animBlogs.initialise();
	}
}

if (window.external && (typeof window.XMLHttpRequest == "object")) {
	// IE7 alternative here
} else {
	addWindowOnLoadEvent(setupAnimateBlogLogos, "network_links");
	// cos the blog logo animation does TEH BADS to the footer in IE7.
}*/
// To use this to isolate IE6, change it to read:
// if (window.external && (typeof window.XMLHttpRequest == "undefined"))
// =)

/***
 * Function: rollDown
 * Reveals an element by doing the following:
 * - sets height to 0 and overflow to hidden.
 * - sets display to block (as it will initially be none).
 * - iteratively increases the height by an ever decreasing value until the initial height is reached,
 *   at which point the decreasing value should be 0. This gives a nice soft-slide effect. V slick.
 * @param theEl
 * - The element to be expanded.
 * @param additive
 * - The ever-decreasing value, as mentioned above. Goes down by 1 in each iteration.
 * @param remainder
 * - The value to add to the height initially so it finishes at just the right height.
 *** NOTE: if the two params above aren't passed, it uses the param below to initialise them.
 * @param elHeight
 * - The original height of the element before it was hidden.
 * @return true
 * - having expanded the object, we simply break out of the function.
 */
function rollDown(theEl,additive,remainder,elHeight)
{
	// If no additive or remainder, get them first.
	if (typeof elHeight == "undefined") { elHeight = 0; }
	var step = 0;
	if (additive == null)
	{
		theEl.style.height = "0px";
		theEl.style.overflow = "hidden";
		theEl.style.display = "block";
		var triangularWithRemainder = new Array;
		triangularWithRemainder = triangle(theEl.initialHeight);
		var additive = triangularWithRemainder[0];
		var remainder = triangularWithRemainder[1];
		triangularWithRemainder = null;
		setTimeout(function(){rollDown(theEl,additive,remainder);},50);
		return;
	} else if (additive == 0)
	{
		return;
	} else if (remainder > 0)
	{
		step = remainder;
		remainder = 0;
	} else
	{
		step = additive;
		additive--;
		if (elHeight < theEl.initialHeight)
		{
			elHeight+=step;
		}
	}
	changeStyle(theEl,"height",elHeight.toString()+"px");
	setTimeout(function(){rollDown(theEl,additive,remainder,elHeight);},50);
}

/***
 * Function: buildElement
 * - Creates an element with whatever attributes you wish, passed in a two-dimensional array.
 * @param elemType
 * - The type of element, eg input, p, span, h4 etc.
 * @param attribs
 * - The array of attribute/value pairs, in the form attribs[x][0] (attribute name), attribs[x][1] (attribute value).
 * @param elemHook
 * - The element in the document to which we add a "hook", which can be referenced using this.hookedElement thereafter.
 * @return theElement
 * - having built the element object, we now return it.
 */
function buildElement(elemType,attribs, elemHook)
{
	theElement = document.createElement(elemType);
	var i;
	for (i=0; i<attribs.length; i++)
	{
		if ((typeof attribs[i][0] == "string") && (typeof attribs[i][1] == "string"))
		{
			theElement.setAttribute(attribs[i][0].toString(), attribs[i][1].toString());
		}
	}
	if ((typeof elemHook == "object") && (elemHook))
	{
		theElement.hookedElement = elemHook;
	}
	return theElement;
}



var displayToggler = function(trgElId , togElId , hdTrg)
{
	this.trgEl = document.getElementById(trgElId);
	this.togEl = document.getElementById(togElId);
	this.hdTrg = (hdTrg)?true:false;
	var objRef = this;
	this.trgEl.onclick = function()
	{
		var d = objRef.togEl.style.display;
		objRef.togEl.style.display = (d == 'none' || d == '')?'block':'none';
		if(objRef.hdTrg)
		{
			objRef.trgEl.parentNode.removeChild(objRef.trgEl);
		}
		return false;
	}
}


var displayWalkthroughToggler = function(trgElId , togElId , hdTrg)
{
	this.trgEl = document.getElementById(trgElId);
	this.togEl = document.getElementById(togElId);
	this.hdTrg = (hdTrg)?true:false;
	var objRef = this;
	this.trgEl.onclick = function()
	{
		var d = objRef.togEl.style.display;
		objRef.togEl.style.display = (d == 'none' || d == '')?'block':'none';
		
		d = objRef.trgEl.style.display;
		objRef.trgEl.style.display = (d == 'none' || d == '')?'block':'none';

		
		if(objRef.hdTrg)
		{
			objRef.trgEl.parentNode.removeChild(objRef.trgEl);
		}
		return false;
	}
	
	Cookie.set("alert_tribal09_dismissed",10, {duration: 9999, path:'/'});
	
}

addWindowOnLoadEvent(function(){
	if (document.getElementById('about_intro'))
	{
		displayWalkthroughToggler('about_intro', 'about_tour', false);
		document.getElementById('about_tour').style.display='none';
		document.getElementById('about_intro').style.display='block';
	}
});

// Clear the default text on Gear Finder keyword field, and restore it if empty on leaving it
// We can add other fields here if we so choose; all we need is the ID of the field.
addWindowOnLoadEvent(function(){clearFormField($("gearfinderKeywords"));}, "gearfinderKeywords");
/* This was commented out, but I'm restoring it here since it's on so many pages it'd be
   ridiculous picking through all the pages just to find out which of 'em doesn't have it.
   The function will trigger if the GFL exists, and won't if it doesn't. Easy. */

// TODO: These should only be called through inclusions of cfg/*.js now.

addWindowOnLoadEvent(function(){clearFormField("soundboard_input");});
// Bookmark form field auto-clearing:
addWindowOnLoadEvent(function(){clearFormField("bookmark_title");},"bookmark_title");
addWindowOnLoadEvent(function(){clearFormField("bookmark_url");},"bookmark_url");
addWindowOnLoadEvent(function(){clearFormField("bookmark_synopsis");},"bookmark_synopsis");


function attachNewWindowEvent()
{
	var imgs = document.getElementsByTagName('img'); 
	for(var i = 0; i < imgs.length; i++)
	{
		if(imgs[i].getAttribute('class') && imgs[i].getAttribute('class').indexOf('js_gallery_main_image') > -1)
		{
			imgs[i].onclick = function()
			{
				var galleryPath = this.parentNode.getAttribute("href");
				w = open(galleryPath,'galleryWindow','width=900,height=800,toolbar=no,status=no,scrollbars=auto,resize=no');
				w.focus();
			}
			imgs[i].parentNode.onclick = function()
			{
				return false;
			}		
		}
	}
}
addWindowOnLoadEvent(attachNewWindowEvent);

//function replaceBrokenImages()
//{
//	var imgs = document.getElementsByTagName('img');
//	var imgNr = imgs.length;
//	for (var img = 0; img < imgNr; img++)
//	{
//		imgs[img].onerror = function()
//		{
//			var originalScr = this.src;
//			var imgSplit = originalScr.split('-');
//			var imgCompression = (imgSplit[imgSplit.length-1].split('.')[0]);
//			var imgFilename = (imgSplit[imgSplit.length-1].split('.')[1]);
//			var imgWidth = (imgSplit[imgSplit.length-2]);
//			if (typeof(imgWidth) == "undefined") {
//				imgWidth = this.width;
//			}
//			if (imgWidth == 0) {
//				if (this.offsetWidth)
//				{
//					imgWidth = this.offsetWidth;
//				}
//			}
//			this.setAttribute('brokenurl' , this.src);
//			this.setAttribute('width' , imgWidth);
//			this.src = 'http://mos.bikeradar.com/images/no-image.jpg'; // just use default.
//			this.setAttribute('alt' , 'Broken Image: ' + this.getAttribute('alt'));
//			this.onerror = null;
//		}
//		imgs[img].src = imgs[img].src;
//	}
//}

//addWindowOnLoadEvent(replaceBrokenImages);

/***
 * Function: triangle
 * Calculate maximum triangular additive and remainder for a given value
 * eg for 58, the maximum triangular number is 1+2+3+4+5+6+7+8+9+10=55
 * with a remainder of 58-55=3, so our values would be 10 and 3.
 * We use this for the thumbnail movement on the Gallery Popup page
 * and the roll-down functionality on the Profile form.
 * @param theVal
 * - A single integer; we use this to find the greatest triangular number smaller than it.
 * @return triWithRem
 * - a two-value array containing the triangular additive and the remainder.
 */
function triangle(theVal)
{
	var additive = 1;
	var theSum = 0;
	do
	{
		if (theSum+additive > theVal)
		{
			// If the next triangular number is bigger than the input value,
			// calculate the remainder by subtracting the input value from the
			// current triangular number and return the current additive and
			// the remainder.
			var triWithRem = [additive,theVal-theSum];
			return triWithRem;
		} else if (theSum+additive == theVal)
		{
			// If the next triangular number is *equal* to the input value,
			// no remainder is needed, so return the next triangular number
			// and a remainder of zero.
			var triWithRem = [additive,0];
			return triWithRem;
		} else
		{
			// If the next triangular number is smaller than the input value,
			// go through the loop again.
			theSum += additive;
			additive++;
		}            
	}
	while(theSum < theVal);
}


/***
 * Function: styleShift
 * Shift a specific style property of a specific element from one value to another.
 * This allows us to "grow" or "shrink" elements, quickyl grow a border around something,
 * transition its background or foreground colour, fade it in or out or even move it from
 * one point to another.
 * The function loops by calling itself using a setTimeout; when the last iteration is detected,
 * the setTimeout is not triggered, thus "ending" the function.
 * @param theElement
 * - the element in the document that's going to be styleshifted.
 * @param propertyName
 * - the style property that will change.
 * @param propertyType
 * - the type of property:
 *   - #�for a hex value, eg for colour values
 *   - o for an opacity value
 *   - % for a percentage value
 *   - x for a pixel value (eg 5px)
 *   - t for a point value (eg 10pt)
 *   - m for a value in ems (eg 2em)
 *   - anything else is treated as a basic numeric value.
 * @param startVal
 * - the initial value.
 * @param endVal
 * - the final value.
 * @param steps
 * - the number of iterations we go through in the transition.
 * @param thisStep
 * - the current iteration.
 * @param delay
 * - the pause between transitions, in milliseconds.
 * @return void
 * - nothing is returned by this function.
 */
function styleShift(theElement,propertyName,propertyType,startVal,endVal,steps,thisStep,delay)
{
	var newVal, startValInt, endValInt;
	switch (propertyType)
	{
		case "#":
		{
			var startRed, startGreen, startBlue, endRed, endGreen, endBlue, redInc, greenInc, blueInc;
			startRed = parseInt(startVal.substring(0,2), 16);
			startGreen = parseInt(startVal.substring(2,4), 16);
			startBlue = parseInt(startVal.substring(4,6), 16);
			endRed = parseInt(endVal.substring(0,2), 16);
			endGreen = parseInt(endVal.substring(2,4), 16);
			endBlue = parseInt(endVal.substring(4,6), 16);
			redInc   = parseInt((endRed - startRed) * (thisStep/steps), 10);
			greenInc = parseInt((endGreen - startGreen) * (thisStep/steps), 10);
			blueInc  = parseInt((endBlue - startBlue) * (thisStep/steps), 10);
			newVal = "rgb(" + parseInt(startRed+redInc) +","+parseInt(startGreen+greenInc) + "," + parseInt(startBlue+blueInc) + ")";
			break;
		}
		case "o":
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10)/100;
			break;
		}
		case "%":
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10).toString()+"%";
			break;
		}
		case "x":
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10).toString()+"px";
			break;
		}
		case "t":
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10).toString()+"pt";
			break;
		}
		case "m":
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10).toString()+"em";
			break;
		}
		default:
		{
			startValInt = parseInt(startVal, 10);
			endValInt = parseInt(endVal, 10);
			newVal = parseInt(startValInt + (endValInt - startValInt) * (thisStep/steps), 10);
		}
	}
	changeStyle(theElement,propertyName, newVal);
	thisStep++;
	if (thisStep <= steps) {setTimeout(function(){styleShift(theElement,propertyName,propertyType,startVal,endVal,steps,thisStep,delay)}, delay);}
}
/***
 * Function: changeStyle
 * Changes the style of one property in one element to a specific value.
 * Useful because it has a catcher in place to handle opacity for MSIE<7.
 * @param div
 * - the element in the document. Awful variable name, should change that.
 * @param change_element
 * - the style property that will change. Again, not a great variable name.
 * @param change_value
 * - the new value of the property.
 * @return void
 * - nothing is returned by this function.
 */
function changeStyle(div,change_element,change_value)
{
  var x = div.style;
  eval('x.'+change_element+' = "'+change_value+'";');
  if (change_element == "opacity")
  {
  	eval('x.filter = "alpha(opacity='+(parseInt(change_value*100)).toString()+')";');
	}
}




/****
* Alert box
*/

function dismissAlert(key)
{
	var el = document.getElementById('alert_dismissable');
	el.style.display='none';
	
	var cookie_num = Cookie.get("alert_" + key + "_dismissed");
	if (cookie_num >= 1)
	{
		cookie_num++;
	}
	else
	{
		cookie_num = 1;
	}
	
//	var cookie_num = parseInt(Cookie.get("alert_" + message)) + 1;
//	document.cookie = "alert_" + key + "_dismissed=" + cookie_num + "; expires=Thu, 1 Jan 2015 23:59:59 UTC; path=/";
	Cookie.set("alert_" + key + "_dismissed",cookie_num, {duration: 9999, path:'/'});
	Cookie.set("alert_" + key + "_seen_today", 6, {duration: 1, path:'/'});
	
}

addWindowOnLoadEvent(function()
	{
		el = document.getElementById('alert_dismiss');
		
		if (el != null)
		{
			el.onclick = function(){dismissAlert('tribal09');};
		}
	},'alert_dismiss');


updatebg = false

function showTakeover() {
	try { 
		enable_takeover();
		clearInterval(updatebg);
	} catch (e) {}
}

addWindowOnLoadEvent(function() {
	try { 
		enable_takeover();
	} catch (e) {
		updatebg = setInterval('showTakeover()',5000);
	}
})

/***
* Revenue Science code
*/
 
//var rsi_segs = [];
//var segs_beg=document.cookie.indexOf('rsi_segs=');
//if(segs_beg>=0){
// segs_beg=document.cookie.indexOf('=',segs_beg)+1;
// if(segs_beg>0){
// var segs_end=document.cookie.indexOf(';',segs_beg);
// if(segs_end==-1)segs_end=document.cookie.length;
// rsi_segs=document.cookie.substring(segs_beg,segs_end).split('|');
//}}
//var segLen=20
//var segQS="";
//if (rsi_segs.length<segLen){segLen=rsi_segs.length}
//for (var i=0;i<segLen;i++){
//   segQS+=("rsi"+"="+rsi_segs[i]+";")
//}
/* End revenue science code */

oldOnLoad = function(){func = function(){return};return}; //fix to anoying ad code

