// ------------------------ 10util.js starts here -----------------------------
/*              Utility functions                    */

ensurePackage('guardian.r2');
guardian.r2.browser = {
	isIE6 : false,
	isIE7 : false,
	isOpera:  !!window.opera,
	isWebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
	isSafari2 : (function () {
		var userAgentNumber = RegExp("( Safari/)([^ ]+)").exec(navigator.userAgent);
		if (!userAgentNumber || userAgentNumber.length < 3) {
			return false;
		}
		var mainVersionNumber = userAgentNumber[2].split('.')[0];
		if (parseInt(mainVersionNumber) > 500) { //This is Safari 3
			return false;
		}
		return true;
	})(),
	isGecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
};

/*@cc_on @*/

/*@if (@_jscript_version <= 5.6)
 // The above conditional compilation for IE is equivalent to
 // a conditional comment in HTML of 'if lte IE 6'
guardian.r2.browser.isIE6 = true;
 /*@end @*/

/*@if (@_jscript_version > 5.6)
 // The above conditional compilation for IE is equivalent to
 // a conditional comment in HTML of 'if lte IE 6'
guardian.r2.browser.isIE7 = true;
 /*@end @*/

function addEvent(obj, eventType, fn){

	if (typeof obj === "string") {
		obj = document.getElementById(obj);
	}

    /* adds an eventListener for browsers which support it
     Written by Scott Andrew: nice one, Scott */
    if (eventType === "load") {
        //hack me
        loadEventList.addLoadEvent(fn);
        return true;
    }
	if (!obj) {
		return null;
	}
    
    if (obj.addEventListener) {
        obj.addEventListener(eventType, fn, false);
        return true;
    }
    else 
        if (obj.attachEvent) {
            var r = obj.attachEvent("on" + eventType, fn);
            return r;
        }
        else {
            return false;
        }
}

function addClickListenersToMatchingElements(inElement, cssRule, clickListenerCallback) {
		
	var elementsToAddListenersTo = guardian.r2.dom.element.getElementsByCssSelector(cssRule, inElement);
	
	for (var i = 0; i < elementsToAddListenersTo.length; i++) {
		addEvent(elementsToAddListenersTo[i], 'click', clickListenerCallback);	
	}
	
};
	
var loadEventList = [];
loadEventList.addLoadEvent = function(fn){
	if(loadEventList.hasFired) {
		fn();
	} else {
		loadEventList[loadEventList.length] = fn;
	}
};

loadEventList.hasFired = false;
loadEventList.fireLoadEvents = function(){
    for (var i = 0; i < loadEventList.length; i++) {
        loadEventList[i]();
    }
    loadEventList.hasFired = true;
};

/* the following is a hack to replicate DOMContentLoaded in browsers
 other than Firefox. 
 */
if (guardian.r2.browser.isWebKit) { // Safari
    var _timer = setInterval(function(){
        if (/loaded|complete/.test(document.readyState)) {
            clearInterval(_timer);
            loadEventList.fireLoadEvents(); // call the onload handler
        }
    }, 100);
}
else 
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", loadEventList.fireLoadEvents, false);
    }
    else {
    // IE HACK
    /*@cc_on @*/
    /*@if (@_win32)
     document.write("<script id='__ie_onload' defer='defer' src='//:'><\/script>");
     var script = document.getElementById("__ie_onload");
     script.onreadystatechange = function() {
	     if (this.readyState == "complete") {
		     loadEventList.fireLoadEvents(); // call the onload handler
	     }
     };
     /*@end @*/
    }

var safeLoadEventList = [];

function addSafeLoadEvent(fn) {
	if (!(guardian.r2.browser.isIE6 || guardian.r2.browser.isIE7)) {
		addEvent(document, 'load', fn);
		return true;
	} else {
		// This is IE6 or 7 and therefore can't have document.body.appendChilds or innerHTMLs until the whole page has loaded.
		// See http://support.microsoft.com/kb/927917 for more information
		safeLoadEventList.push(fn);
		return true;
	}
}

safeLoadEventList.hasFired = false;
safeLoadEventList.fireLoadEvents = function() {
    for (var i = 0; i < safeLoadEventList.length; i++) {
        safeLoadEventList[i]();
    }
    safeLoadEventList.hasFired = true;
};

if ((guardian.r2.browser.isIE6 || guardian.r2.browser.isIE7)) {
	window.attachEvent("onload", safeLoadEventList.fireLoadEvents);
}


function importScript(src, onloadCallback, forceIEtoUseTimers, notifyOnState, onerrorCallback){
	var scriptElem = document.createElement('script');
	scriptElem.setAttribute('src',src);
	scriptElem.setAttribute('type','text/javascript');
	
	notifyOnState = (notifyOnState ? notifyOnState : 'loaded');
	
	if (onloadCallback) {
		
	
	
        if (guardian.r2.browser.isSafari2 || guardian.r2.browser.isOpera || (forceIEtoUseTimers && (guardian.r2.browser.isIE6 || guardian.r2.browser.isIE7))) { // sniff
			importScript.guardianImportScriptTimers[src] = setInterval(function() {
				
				if (/loaded|complete/.test(document.readyState)) {
					clearInterval(importScript.guardianImportScriptTimers[src]);
					try {
						onloadCallback(); // call the callback handler
					} catch (e) {
						if(onerrorCallback) {
							onerrorCallback();
						}
					}
				}
				
			}, 10);
	
		} else {
			// and now the browsers that WORK
			
			scriptElem.onreadystatechange = function () {
			
				if (scriptElem.readyState === 'notifyOnState') {
					onloadCallback();
				}
			};
			scriptElem.onload = onloadCallback;
			scriptElem.onerror = function(){ 
				if(onerrorCallback){
					onerrorCallback();
				}
			};
			
		}
	}

	document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
importScript.guardianImportScriptTimers = {};


function openGalleryPopup(url, height){
    var galleryWidth = 830;
    var leftPos = calculateXForCentredPopup(galleryWidth);
    var newWindow = window.open(url, '_blank', 'resizable=yes,scrollbars=yes,location=yes,toolbar=yes,status=no,top=0,screenY=0,left=' + leftPos + ',screenX=' + leftPos + ',height=' + height + ',width=' + galleryWidth);
    return false;
}

function calculateXForCentredPopup(popupWidth) {
    var leftPos = 0;
    if (screen.availWidth > popupWidth) {
        leftPos = Math.round((screen.availWidth - popupWidth) / 2);
    }
    
    return leftPos;
}


function openScorePopup(url){
 	var height= 335;
	var width = 420;
    var leftPos = 0;
    window.open(url, '_blank', 'resizable=yes,scrollbars=yes,location=no,toolbar=no,status=no,top=0,screenY=0,left=' + leftPos + ',screenX=' + leftPos + ',height=' + height + ',width=' + width);
    return false;
}

function popUpNewWindow(url,width,height) {
	newwindow=window.open(url,'sponsor','height=' + height + ',width=' + width + ',scrollbars=yes,location=yes,toolbar=yes,status=yes,resizable=yes');
	if (window.focus) {newwindow.focus()}
	return false;
}

function forEachElementOf(list, doThis){
    var listLength = list.length;
    for (var i = 0; i < listLength; i++) {
        doThis(list[i], i);
    }
}

function readCookie(name) {
    var nameEQ = name + "=";
    var cookieArray = document.cookie.split(';');
	
    for (var i = 0; i < cookieArray.length; i++) {
        var cookie = cookieArray[i];
		
        while (cookie.charAt(0) == ' ') {
			cookie = cookie.substring(1, cookie.length);
		}
			
        if (cookie.indexOf(nameEQ) === 0) {
			return cookie.substring(nameEQ.length, cookie.length);
		}
    }
	
    return null;
}

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function isExternalSystemOn(system){

    var extSystems = readCookie("GU_EXT_SYS");
    if (extSystems !== null) {
        return extSystems.match(system) === null;
    }
    return true;
}

function isUserLoggedIntoRegPss() {
	return readCookie("GU_ME") != null;
}

function generateScriptTag(src){
    document.write('<script type="text/javascript" src="' + src + '"></scr' + 'ipt>');
    document.close();
}

function getScrollPosition(){
    var scrollX, scrollY;
    if (self.pageYOffset) {
        scrollX = self.pageXOffset;
        scrollY = self.pageYOffset;
    }
    else 
        if (document.documentElement && document.documentElement.scrollTop) {
            scrollX = document.documentElement.scrollLeft;
            scrollY = document.documentElement.scrollTop;
        }
        else 
            if (document.body) {
                scrollX = document.body.scrollLeft;
                scrollY = document.body.scrollTop;
            }
    return {
        x: scrollX,
        y: scrollY
    };
}

function getCenterPosition(){
    var centerX, centerY;
    if (self.innerHeight) {
        centerX = self.innerWidth;
        centerY = self.innerHeight;
    }
    else 
        if (document.documentElement && document.documentElement.clientHeight) {
            centerX = document.documentElement.clientWidth;
            centerY = document.documentElement.clientHeight;
        }
        else 
            if (document.body) {
                centerX = document.body.clientWidth;
                centerY = document.body.clientHeight;
            }
    return {
        x: centerX,
        y: centerY
    };
}

function getScrollAndCenterPosition(){
    var scroll = getScrollPosition();
    var center = getCenterPosition();
    return {
        scrollX: scroll.x,
        scrollY: scroll.y,
        centerX: center.x,
        centerY: center.y
    };
}

function fixFirefoxIncrementalReflowBug() {
	if (window.getComputedStyle) {
		// This is only required for Firefox 2, where the incremental rendering sometimes gets messed
		// up. Call this to force a document reflow. This bug is (apparently) fixed in FF3.
		var body = document.getElementsByTagName('body')[0];
		var bodyHeight = window.getComputedStyle(body,'').getPropertyValue('height');
		body.style.height = bodyHeight;
		window.setTimeout(function () {body.style.height = 'auto'},100);
	}
}

function GUopenParent(target) {
	if (window.opener) {
		window.opener.location=target;
	} else {
		location=target;
	}
}

function classNameRegex(cl) {
	return new RegExp("( |^)" + cl + "( |$)")
}

function removeClassName(el, className) {
	 el.className = el.className.replace(classNameRegex(className), " ").replace(/(^\s*|\s*$)/g, '');
}

function getAncestorOfType(object, tagType) {
	if(!object.tagName) {
		return null;
	} else {
		return (object.tagName.toLowerCase() === tagType) ? object : getAncestorOfType(object.parentNode, tagType);
	}
}


function arrayIndexOf(array, value) {
	for (var i = 0; i < array.length; i++) {
		if (array[i] === value) {
			return i;
		}
	}
	return -1;
}

function isArray(value){
	
	return value &&	
		typeof value === 'object' &&
		typeof value.length === 'number' &&
		typeof value.splice === 'function' &&
		!(value.propertyIsEnumerable('length'));
	
}
	
function arrayContains(theArray, theValue) {
	for (var i = 0; i < theArray.length; i++) {
		if (theArray[i] === theValue) {
			return true;
		}
	}
	return false;
}

// ---------------//---------- 10util.js ends here ------------------------------














// ------------------------ 12non-browser-utils.js starts here -----------------------------
function ensurePackage(packageName, packageBlock){
    var package_parts = packageName.split(".");
    var package_so_far = this;
    for (var i = 0; i < package_parts.length; i += 1) {
        var package_part = package_parts[i];
        if (!package_so_far[package_part]) {
            package_so_far[package_part] = {};
        }
        package_so_far = package_so_far[package_part];
    }
    if (packageBlock) {
        packageBlock(package_so_far);
    }
    return package_so_far;
}

function trim(str) {
	return ltrim(rtrim(str));
}

function ltrim(str) {
	return str.replace(/^\s+/, '');
}

function leftTrim(str){
    return str.replace(new RegExp(/^\s*/g), "");
}

function rtrim(str) {
	return str.replace(/\s+$/, '');
}

function stripParamFromUrl(param, urlToStrip) {
	var paramterValueExpression = "=[\\w\\-]*";
	var url = urlToStrip.replace(new RegExp("\\?" + param + paramterValueExpression + "$"), ""); // first and only param
	url = url.replace(new RegExp("\\?" + param + paramterValueExpression +  "&"), "?"); // first of many params
	url = url.replace(new RegExp("&" + param + paramterValueExpression), ""); // not first param
	return url;	
}

function isNumber(value) {
	return typeof value === 'number';
}

function delegateErrorHandler(to, from) {
	to.errorHandler = from.errorHandler;
}

function isValidUrl(url) {
	var regexp = /(http:\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
	return regexp.test(url);
}

function appendParameter(url, parameter) {
	if (url.indexOf('?') !== -1) {
		return url + '&' + parameter;
	} else {
		return url + '?' + parameter;
	}
}

function isArray(object) {
	return object != null && typeof object == "object" && 'splice' in object && 'join' in object;
}

// ------------------------ 12non-browser-utils.js ends here -----------------------------












ensurePackage('guardian.r2');

guardian.r2.dom = {
	
	element : new function () {
		var instance = this;
		
		function hasClassNameFunction(className) {
			var classNameRegExp = new RegExp('(^| )' + className + '( |$)');
			return function (inputElement) {
				return classNameRegExp.test(inputElement.className);
			};
		}

		this.hasClassName = function (inputElement, className) {
			return hasClassNameFunction(className)(inputElement);
		};
		
		this.addClassName = function (inputElement, className) {
			if (!instance.hasClassName(inputElement, className)) {
				inputElement.className += ' ' + className;
				inputElement.className = inputElement.className.replace(/^\s|\s$/, '');
			}
		}
		
		//syntax : 'li.pixie a.class-name'. Only supports class & tag Names
		this.getElementsByCssSelector = function (cssExpression, parentElement) {
			
			if (isArray(cssExpression)) {
				var results = [];
				var cssExpressionLength = cssExpression.length;
				for (var i = 0; i < cssExpressionLength; i++) {
					results = results.concat(getElementsByIndividualCssSelector(cssExpression[i], parentElement));
				}
				return results;
			}
			return getElementsByIndividualCssSelector(cssExpression, parentElement);
			
		};

		var getElementsByIndividualCssSelector = function (cssExpression, parentElement) {
			var cssParts = cssExpression.split(' ');
			var firstTagAndClassNamePair = cssParts[0];
			var moreTagAndClassNamePairs = cssParts.slice(1).join(' ');
			
			// extract tag and classname
			var firstTagAndClassNamePairSplit = firstTagAndClassNamePair.split('.'); 
			var tagType = firstTagAndClassNamePairSplit[0];
			var className = firstTagAndClassNamePairSplit[1];
			
			var selectedElements = instance.getElementsByClassName(className, tagType, parentElement);

			if (moreTagAndClassNamePairs) { // If this exists, then we want to process the child elements
				var matchingElementList = [];
				var selectedElementsLength = selectedElements.length;
				var getElementsByCssSelector = instance.getElementsByCssSelector;
				for (var i = 0; i < selectedElementsLength; i++) {
					// recurse
					matchingElementList = matchingElementList.concat(getElementsByCssSelector(moreTagAndClassNamePairs, selectedElements[i]));
				}
				return matchingElementList; //This produces the final result.
			}
			return selectedElements;
		};

		this.getElementsByClassName = function(className, tagType, parentElement) {
		
			parentElement = parentElement ? parentElement : document;
			className = className ? className : null;
			
			if (!!document.evaluate && className) {
				var expression;
				if (tagType) {
					expression = ".//" + tagType + "[contains(concat(' ', @class, ' '), ' " + className + " ')]";
				} else {
					expression = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
				}
				var query = document.evaluate(expression, parentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				
				var results = [];
				for (var i = 0, length = query.snapshotLength; i < length; i++) {
					results.push(query.snapshotItem(i));
				}
				
				return results;
			}

			tagType = tagType ? tagType : '*';

			var matchingTags = parentElement.getElementsByTagName(tagType);
			if (className) {
				var matchingElements = [];
				var matchingTagsLength = matchingTags.length;
				var elementHasSuppliedClassName = hasClassNameFunction(className);
				for (var  i = 0; i < matchingTagsLength; i++) {
					if (elementHasSuppliedClassName(matchingTags[i])) {
						matchingElements.push(matchingTags[i])
					}
				}
				return matchingElements;
			}
			return convertNodeListToArray(matchingTags);

		};
		
		var convertNodeListToArray = function (listLikeObject) {
			var currentPlace = listLikeObject.length;
			var results = [];
			while (currentPlace--) {
			    results[currentPlace] = listLikeObject[currentPlace];
			}
			return results;
		}
	},
	
	form : new function () {
		var instance = this;
		var inputTags = ['input', 'textarea', 'select'];
		this.serializeForm = function (domForm) {
			var serializedFields = [];
			for (var i = 0; i <inputTags.length; i++) {
				var fields = domForm.getElementsByTagName(inputTags[i]);
				for (var j = 0; j < fields.length; j++) {
					var field = fields[j];
					if (!field.disabled && field.name) {
						serializedFields.push(instance.serialize(field));
					}
				}
			}
			var formAction = domForm.action;
			return serializedFields.join('&');
		};
		
		this.serialize = function (element) {
			var tagType = element.tagName.toLowerCase();
			var elValue = null;
			switch (tagType) {
			case 'textarea':
				elValue = element.value;
				break;
			case 'input':
				switch (element.type.toLowerCase()) {
				case 'radio':
				case 'checkbox':
					elValue = element.checked ? element.value : null;
					break;
				default:
					elValue = element.value;
					break;
				}
				break;
			case 'select':
				var selectedOptions = [];
				for(var k = 0; k < element.options.length; k++){
					if(element.options[k].selected){
						selectedOptions.push(element.options[k].value ? element.options[k].value : element.options[k].text);
						if(!element.multiple) {
							break;
						}
					}
				}
				if (selectedOptions.length > 0) {
					elValue = selectedOptions.join(',');
				}
			}				
			
			if(elValue !== null){
				return encodeURIComponent(element.name) + "=" + encodeURIComponent(elValue);
			}
			
		}
	}
}
// --------------------------------- event.js -------------------------------------------





// --------------------- font-sizer.js starts here ----------------------------
/*
	this script adjusts the font-size of the document in 10% increments.
	it checks for the sizing-widget id and then attaches click events 
	it also sets a cookie to rember the font size for 1 year form the last visit

*/

/*
	if javascript is turned off the links goto larger.html and smaller.html
	these pages should explain about what the widget is for and how to adjust 
	the font-size in the browser...
*/

addEvent(window, "load", fontSizer);
addEvent(window, "load", fontSizerSidebar);
addEvent(window, "load", setFontSize);

function fontSizer() {
	_fontSizer(document.getElementById('larger'), document.getElementById('smaller'));
}

function fontSizerSidebar() {
	_fontSizer(document.getElementById('larger-sidebar'), document.getElementById('smaller-sidebar'));
}

function _fontSizer(increase, decrease) {
	
	if (!increase || !decrease) {
		return;
	}

	increase.style.display="inline";
	decrease.style.display="inline";
	
	var myDate= new Date();
	expires=myDate.getFullYear()+1
	myDate.setFullYear(expires);
	expires='; expires='+myDate.toGMTString();
	
	increase.onclick= function() {
		//get the calculated font-size
		if (document.getElementsByTagName('body')[0].style.fontSize)  {
			var currentSize=document.getElementsByTagName('body')[0].style.fontSize;
			
			currentSize=currentSize.match(/([0-9]+)/);
			currentSize=(Number(currentSize[0])+10)+'%';

		}else{//no calculated font size so we are just starting
			var currentSize='110%';
		}
		
		document.getElementsByTagName('body')[0].style.fontSize=currentSize;
		document.cookie="fontSize="+currentSize+expires;
		return false;
	}
	
	decrease.onclick= function() {
		//get the calculated font-size
		if (document.getElementsByTagName('body')[0].style.fontSize)  {
			var currentSize=document.getElementsByTagName('body')[0].style.fontSize;
			currentSize=currentSize.match(/([0-9]+)/);
			currentSize=(Number(currentSize[0])-10);
			if (currentSize<60) currentSize=60;
			currentSize=currentSize+'%';
		} else {//no calculated font size so we are just starting
			var currentSize='90%';
		}
		document.getElementsByTagName('body')[0].style.fontSize=currentSize;
		document.cookie="fontSize="+currentSize+expires;
		return false;
	}
}

/*
	Get the cookie and set the adjusted font-size
*/

function setFontSize ()  {
	var cookies=document.cookie;
	var cookieList=cookies.split(';');
	var fontSize='';

	for ( var i=0; i<cookieList.length; i++)  {
		if (cookieList[i].match('fontSize')) fontSize=cookieList[i];
	}
	if (fontSize)  {	
		fontSize=fontSize.match((/([0-9]+\%)/))[0];
		document.getElementsByTagName('body')[0].style.fontSize=fontSize;
	}
}
// ---------------------- font-sizer.js ends here -----------------------------
