nsCustomRun = true;
/**
 * Initiate tracking statistics as the first task we perform.
 */
$.getScript('/js/tracker/tracker.js.php?mode=default');
$.getScript('/js/tracker/googleAnalytics.js.php?mode=default');

/**
 * Sitewide javascript variables.
 */
var section = "project-management";
var group = "dsdm-atern";

/**
 * The following section monitors the loading of external JS files and triggers registered callbacks when the specified
 * files have loaded.
 */

// Keep a record of the files which have successfully loaded. This is used such that if an event listener is registered
// with a dependency on the load of a file that *has already loaded*, the listener can be called immediately.
var jsLoadedFiles = [];

// An associative array. The key is the callback function, which is called when all javascript files specified as an
// array in the value have loaded.
var jsLoadListeners = [];

// An array which stores callback functions that only care when ALL javascript files have loaded, rather than specific
// files.
jsLoadCompleteListeners = [];

// At a basic level, if we have a count of the number of JS files being loaded, and we decrement this upon each
// completion, we will know that ALL files have loaded once this counter reaches zero.
var jsLoadCount = 0 + 13;



if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0) ? Math.ceil(from) : Math.floor(from);

		if (from < 0)
		{
			from += len;
		}

		for (; from < len; from++)
		{
			if (from in this &&	this[from] === elt)
			{
				return from;
			}
		}
		return -1;
	};
}


/**
 * Extend the intrinsic Array object to provide a method which can subtract from it a given array.
 */
Array.prototype.subtract = function (withArray)
{
	for(var i=0; i < withArray.length; i++)
	{
		elIndex = this.indexOf(withArray[i]);

		if(elIndex >= 0)
		{
			this.splice(elIndex, 1);
		}
	}
};



/**
 * This function will register a callback function to be triggered either when ALL javascript has loaded (leave
 * filesRequired as undefined) or when specific javascript files have loaded (specify as an array in filesRequired).
 */
function registerJSLoadListener(callback, filesRequired)
{
	// If filesRequired was not specified, this is a callback to be executed when ALL javascript has loaded.
	if(filesRequired === undefined)
	{
		jsLoadCompleteListeners[jsLoadCompleteListeners.length] = callback;
	}
	else
	{
		var i = jsLoadListeners.length;

		// Use a temporary array to perform the addition of the listener and the subtracting of files that have already
		// loaded in one atomic action as far as the jsLoadListeners array is concerned. Failing to do this causes
		// sporadic errors if triggerJSLoadListeners is called and checks the size of the array between the two operations.
		var tempJSLoadListeners = [callback, filesRequired];
		tempJSLoadListeners[1].subtract(jsLoadedFiles);
		jsLoadListeners[i] = tempJSLoadListeners;

		// If all the files specified had already loaded, trigger the callback immediately.
		if(jsLoadListeners[i][1].length <= 0)
		{
			callback();  // Small chance of race condition here.
			jsLoadListeners.splice(i, 1);
		}
	}
}



/**
 * This function is called every time a JS file completes loading.
 */
function triggerJSLoadListeners(fileLoaded)
{
	// One more file has been loaded so decrement the load count and record the loaded files name.
	jsLoadCount--;
	jsLoadedFiles[jsLoadedFiles.length] = fileLoaded;

	// If the jsLoadCount is zero, everything has loaded. As a safety feature, we specify *exactly* zero, so that if for
	// some reason the count drops below zero functions aren't triggered more than once.
	if(jsLoadCount == 0)
	{
		// All javascript files have loaded so call the loadCompleteListeners.
		for(var i=0; i < jsLoadCompleteListeners.length; i++)
		{
			jsLoadCompleteListeners[i]();
		}
	}

	// Check all remaining callback functions to determine whether this file load should trigger any of them.
	for(var i=0; i < jsLoadListeners.length; i++)
	{
		var fileIndex = jsLoadListeners[i][1].indexOf(fileLoaded)

		// If the file was one of the requirements of this callback, remove it now.
		if(fileIndex >= 0)
		{
			jsLoadListeners[i][1].splice(fileIndex, 1);

			// If this callback has a length of zero or less, trigger the callback and then remove it so that it can not be
			// called twice.
			if(jsLoadListeners[i][1].length <= 0)
			{
				jsLoadListeners[i][0]();  // Small chance of race condition here.
				jsLoadListeners.splice(i, 1);
			}
		}
	}
}



/**
 * Load specified additionalJS files. Much cleaner than doing this in the HTML head.
 */
$.getScript("/js/rsh04/dhtmlHistory.js", function () { triggerJSLoadListeners('/js/rsh04/dhtmlHistory.js'); });
$.getScript("/js/jQuery/jquery.form.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.form.js'); });
$.getScript("/js/script.js", function () { triggerJSLoadListeners('/js/script.js'); });
$.getScript("/js/md5.js", function () { triggerJSLoadListeners('/js/md5.js'); });
$.getScript("/js/user.js", function () { triggerJSLoadListeners('/js/user.js'); });
$.getScript("/js/positioning.js", function () { triggerJSLoadListeners('/js/positioning.js'); });
$.getScript("/js/jQuery/jquery.easing-1-1.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.easing-1-1.js'); });
$.getScript("/js/jQuery/jquery.dimensions.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.dimensions.js'); });
$.getScript("/js/jQuery/jquery.interface.pack.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.interface.pack.js'); });
$.getScript("/js/jQuery/jquery.timers-1.1.2.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.timers-1.1.2.js'); });
$.getScript("/js/jQuery/jquery.overlabel.js", function () { triggerJSLoadListeners('/js/jQuery/jquery.overlabel.js'); });
$.getScript("/js/coursePage.js", function () { triggerJSLoadListeners('/js/coursePage.js'); });
$.getScript("/js/dates.js", function () { triggerJSLoadListeners('/js/dates.js'); });

//$.getScript("/wce/webeditor.js", function () { triggerJSLoadListeners('/wce/webeditor.js'); });
//$.getScript("/js/stuffedTracker/tracker.js", function () { triggerJSLoadListeners('/js/stuffedTracker/tracker.js'); });



/**
 * ON DOCUMENT READY FUNCTION
 */
$(function ()
	{
		// Initialise JS Dark Ribbon
		$('.dark_menu_list_item')
			.bind('mouseover', function () { showRibbon(this); })
			.bind('mouseout', function (event) { checkMenu(event, this); });

		// Initialise JS Light Ribbon
		$('.white_ribbon_top, .white_ribbon_bottom')
			.bind('mouseout', function (event) { checkMenu(event, this); })
			.bind('mouseover', function () { $('.dark_menu_list_item_active').stopTime(); });

		// Execute any additional on ready JS sent from the server.
	});





/**
 * Create and position an overlay which appears to dim the content behind it.
 * Other content can then be positioned on top of this dimmed screen.
 *
 * @param String id A unique ID for the object. Use this when dimming the screen more than once at the same time.
 * @param int z A value for the Z-Index of the dimming layer.  Use this when you wish to dim multiple times.
 */
function dimScreen(callback, z, id)
{
	if(z == null) z = 100;
	if(id == null) id = "overlay";

	// Check whether a dimmer layer by this name exists and if so, adjust it's z-index.
	if($("div#"+id).size() > 0)
	{
		$("div#"+id).css({"z-index": z});
	}
	else
	{
		$("body").prepend('<div id="'+id+'" class="overlay" style="z-index: '+z+'"></div>');
	}
	if(callback) callback();
}

/**
 * Remove an already existing dimming layer from the screen.
 *
 * @param String id The ID for the dimming layer. Leaving this blank will assume the default.
 */
function undimScreen(callback, id)
{
	if(id == null) id = "overlay";

	$("div#"+id).remove();
	//$("div#"+id).fadeOut("normal", function() {$("div#"+id).remove();});
	if(callback) callback();
}



var statusImageTimers = [];

/**
 * Display an animated status image in the centre of the page.
 *
 * @param String id A unique ID for the object. Use this when displaying more than one status image at the same time.
 * @param int z A value for the Z-Index of the image.  Use this when you've altered the Z-Index of the dimming layer.
 * @param String imageName The name of the image containing the text to place on top of the status animation.
 */
function displayStatusImage(imageName, z, id, minimumDisplayMS)
{
	if(z == null) z = 150;
	if(id == null) id = "statusImage";
	if(imageName == null) imageName = "/images/statusImages/statusLoading.png";
	if(minimumDisplayMS == null) minimumDisplayMS = 2000;

	h=100; w=100;

	screenDimensions = getScreenDimensions();
	scrollOffsets = getScrollOffsets();

	vPosition = scrollOffsets[1] + (screenDimensions[1] / 2) - (h/2);
	//hPosition = (screenWidth / 2) - (w/2);
	hPosition = (w/2);

	$("body").append('<div class="horizontalHorizon" style="z-index: '+z+'; position:absolute; top:'+vPosition+'px;"><div id="'+id+'" class="statusImage" style="z-index: '+z+'"><img src="/images/statusImages/statusAnimation.gif" style="position:absolute" /><img src="'+imageName+'" /></div></div>')

	statusImageTimers[id] = [new Date(), minimumDisplayMS];

	// Return the millisecond value when the statusImage was created for use in minimum display time.
	return new Date();
}

/**
 * Destroy an existing status image.
 *
 * @param String id The unique ID for the status image to be destroyed. Blank will assume the default.
 */
function destroyStatusImage(callback, id)
{
	if(id == null) id = "statusImage";

	// Check that this image has been displayed for the minimum time.
	var currentTime = new Date();
	var timeLeft = statusImageTimers[id][1] - (currentTime - statusImageTimers[id][0]);

	if(timeLeft > 0)
	{
		setTimeout("destroyStatusImage2('"+id+"', "+callback+")", timeLeft);
		return;
	}
	destroyStatusImage2(id, callback);
}

function destroyStatusImage2(id, callback)
{
	$("div#"+id).remove();

	if(callback) callback();
}



function displayHTMLPopup(h, w, title, source, noTitle, z, id, minimumDisplayMS)
{
	if(minimumDisplayMS == null) minimumDisplayMS = 300;
	if(noTitle == null) noTitle = false;

	extraCSS = "";
	isImage = false;
	var imageFileTypes = new Array();
	imageFileTypes[".png"] = 1;
	imageFileTypes[".jpg"] = 1;
	imageFileTypes[".gif"] = 1;
	imageFileTypes[".bmp"] = 1;

	if(z == null) z = 150;
	if(id == null) id = "htmlPopup";

	dimScreen();

	if(noTitle)
	{
		$("div#overlay").css("background-color", "#6f8aa8");
	}

	if(imageFileTypes[source.substring(source.lastIndexOf("."), source.length)] == 1)
	{
		displayStatusImage(null, null, null, 0);

		isImage = true;
		extraCSS = "overflow: hidden";
		image = new Image();
		image.onload =  function () { displayHTMLPopup2(h, w, title, source, noTitle, z, id, minimumDisplayMS) };
		image.onerror =  function () { alert('Error loading photograph.'); };
		image.src = source;
	}
	else
	{
		displayHTMLPopup2(h, w, title, source, noTitle, z, id, minimumDisplayMS);
	}
}

function displayHTMLPopup2(h, w, title, source, noTitle, z, id, minimumDisplayMS)
{
//	noTitle=true;
	// Now the image has loaded, get its size.
	if(isImage)
	{
		if(!w) w = image.width + 20;
		if(!h) h = image.height + 20;

		destroyStatusImage();
	}

	if (!noTitle)
	{
		imgH=h-20;
	}
	else
	{
		imgH=h;
	}

	newContent = '<div id="'+id+'" style="height: '+h+'px; width: '+w+'px; visibility:hidden" class="htmlPopup">'
				+'		<div id="'+id+'Content" class="htmlPopupContent" style="height: '+imgH+'px;'+extraCSS+'">'
				+'		</div>';

	if(!noTitle)
	{
		newContent = newContent+'		<div style="font-size:1.4em; font-weight:bold; padding-left:10px; padding-right:10px; text-align:center;">'+title+'</div>';
	}

	newContent = newContent+'	</div>';


	$("body").append(newContent);

	// If this is an image, handle directly with no AJAX call.
	if(isImage)
	{
		$("div#htmlPopupContent").append('<img src="'+source+'" class="htmlPopupImage" />');

		htmlPopupT = null;

		$("#htmlPopup").centre();
		$('#htmlPopup').css("display", "none").css("visibility", "visible");
		$(window).bind("resize", function() { $('#htmlPopup').centreVertically(); });
		$(window).bind("scroll", function() { clearTimeout(htmlPopupT); htmlPopupT = setTimeout("$('#htmlPopup').centreVertically();", 100); });

		$("div#htmlPopup").fadeIn("normal");
	}
	else
	{
		displayStatusImage(null, null, null, minimumDisplayMS);

		// Make an ajax call for the content and set the callback.
		$.ajax({url: "/ajax"+source, success: displayHTMLPopupContent});
	}

	$("div#overlay").bind("click", function () { destroyHTMLPopup(id, undimScreen); });
	$('#htmlPopup').bind("click", function () { destroyHTMLPopup(id, undimScreen); });
}

function displayHTMLPopupContent(xmlHttp)
{
	/*
		This is a big hack. Basicly, for some strange reason, if the .append function
		is called to soon, Safari crashes. I'm guessing it might have something to do with the fact
		that destroyStatusImage is called asynchronously from displayStatusImage, so they might be
		in race condition. However, for now, simply for loop loads lol!
	*/
	for (i = 0; i < 100000; i++){

	}

	$("div#htmlPopupContent").append(xmlHttp.responseText);
	destroyStatusImage(displayHTMLPopupContent2);
}

function displayHTMLPopupContent2()
{
	verticalCentre("htmlPopup"); $("#htmlPopup").css("visibility", "visible");
	window.onresize = function() {	verticalCentre("htmlPopup") };
	window.onscroll = function() {	verticalCentre("htmlPopup") };

	$("div#htmlPopup").fadeIn("normal");
}

function destroyHTMLPopup(id, callback, noTitle)
{
	if(id == null) id = "htmlPopup";

	if(noTitle)
	{
		$("div#shadowdiv").show();
		$("div#headershadowdiv").show();
		$("div#bottomSpacer").show();
		$("div#cart_feedback").show();
		$("div#standard_bar").show();
	}

	$("div#"+id).fadeOut("normal", function () { $("div#"+id).remove(); callback(); });
}


function isset(varname)
{
  return (typeof(window[varname])!='undefined');
}


function goToPage(page)
{
	var pages = new Array();
	pages["myAccount"] = "/mytcc/myaccount.php";

	document.location.href = pages[page];
}








/* METHODS UNDER DEVELOPMENT OR RETIRED */
function center(div)
{
	// Get relevant sizings.
	var pagesize = getPageSize();
	var divsize = getDivSize(div);

	$("#RG_feedback").css({left: ((pagesize[0]/2)-(divsize[0]/2))+"px", top: ((pagesize[1]/2)-(divsize[1]/2))+"px"});
}

function getPageSize()
{
	var de = document.documentElement;
	var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
	var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight
	arrayPageSize = new Array(w,h)
	return arrayPageSize;
}

function getDivSize(div)
{
	var w = div.offsetWidth; // || div.document.width;
	var h = div.offsetHeight; // || div.document.height;

	arrayDivSize = new Array(w,h)
	return arrayDivSize;
}

// Not sure if this works.
function getPageScrollTop(){
	var yScrolltop;
	var xScrollleft;
	if (self.pageYOffset || self.pageXOffset) {
		yScrolltop = self.pageYOffset;
		xScrollleft = self.pageXOffset;
	} else if (document.documentElement && document.documentElement.scrollTop || document.documentElement.scrollLeft ){	 // Explorer 6 Strict
		yScrolltop = document.documentElement.scrollTop;
		xScrollleft = document.documentElement.scrollLeft;
	} else if (document.body) {// all other Explorers
		yScrolltop = document.body.scrollTop;
		xScrollleft = document.body.scrollLeft;
	}
	arrayPageScroll = new Array(xScrollleft,yScrolltop)
	return arrayPageScroll;
}


function setScrollY(scrollY)
{
	var scrollX, scrollY;
	if (self.pageYOffset) // all except Explorer
	{
		self.pageYOffset = scrollY;
	}
	else if (document.documentElement && document.documentElement.scrollTop) // Explorer 6 Strict
	{
		document.documentElement.scrollTop = scrollY
	}
	else if (document.body) // all other Explorers
	{
		document.body.scrollTop = scrollY;
	}
}

function getScrollOffsets()
{
	var scrollX, scrollY;
	if (self.pageYOffset) // all except Explorer
	{
		scrollX = self.pageXOffset;
		scrollY = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop) // Explorer 6 Strict
	{
		scrollX = document.documentElement.scrollLeft;
		scrollY = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		scrollX = document.body.scrollLeft;
		scrollY = document.body.scrollTop;
	}
	return new Array(scrollX, scrollY);
}
function getScreenDimensions()
{
	var screenX, screenY;
	if (self.innerHeight) // all except Explorer
	{
		screenX = self.innerWidth;
		screenY = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight) // Explorer 6 Strict Mode
	{
		screenX = document.documentElement.clientWidth;
		screenY = document.documentElement.clientHeight;
	}
	else if (document.body) // other Explorers
	{
		screenX = document.body.clientWidth;
		screenY = document.body.clientHeight;
	}
	return new Array(screenX, screenY);
}


Array.prototype.in_array = function(search_term) {
  var i = this.length;
  if (i > 0) {
	 do {
		if (this[i] === search_term) {
		   return true;
		}
	 } while (i--);
  }
  return false;
}
