/**
* @fileoverview This is a general Common class, containing a set of methods specifically useful when developing the EastEnders site 2007.
*/

/**
* @constructor
*/
function Common () {this.init();}

Common.prototype = {

	init : function () {
		
		// Init array for fading elements
		this.fadeElems = []
		this.aLen = 0;
		
		// Get Ajax request object, browser detection
		// IE
		if(window.ActiveXObject){
			this.requestObject = new ActiveXObject("Microsoft.XMLHTTP");
		// Standards compliant
		} else if (window.XMLHttpRequest){
			this.requestObject = new XMLHttpRequest();
		// Neither
		} else {
			this.requestObject = false;
		}
		
	},
	
	
	/**
	* $ - Prototype $ function. Accepts element ID's (strings) and HTML objects as arguments. Returns an array of objects.      
	* 
	* Usage: Common.$("someID", "someID2", aDivElement, aImgElement); 
	*
	* Author - Prototype library
	*/
	$ : function() {
	
		var elements = new Array();
		
		for (var i = 0; i < arguments.length; i++) {
		
			var element = arguments[i];
		
			if (typeof element == 'string') element = document.getElementById(element);
		
			if (arguments.length == 1) return element;
			
			elements.push(element);
		}
		return elements;
	},

	/**
	* Adds and event listener to the specified element
	* 
	* @param {Object} obj The HTML element on which to add the event
	* @param {String} evType The event type, ie. load, change, mousedown
	* @param {Function} fn The function that is to be triggered by the event.
	* @param {Boolean} useCapture Use Event Capture. Set to false
	*
	* @author http://www.scottandrew.com/weblog/articles/cbs-events
	*
	*/
	addEvent : function (obj, evType, fn, useCapture) {
		if (obj.addEventListener) {
			obj.addEventListener(evType, fn, useCapture);
			return true;
		}
		else if (obj.attachEvent) {
			var r = obj.attachEvent('on' + evType, fn);
			return r;
		}
		else {
			obj['on' + evType] = fn;
		}
	},
	

	/**
	* Handles and returns the response from the doAjaxSend() method. 
	*
	* @see #doAjaxSend
	* @return Returns the response from the Ajax request
	* @throws Common.ajaxError() Throws the Common.ajaxError() function on a fialed request. Default is an alert box explaining the error with the returned status of the ajax request.
	*
	*/
	doAjaxResponse : function() {

	    // If response is complete
	    if(Common.requestObject.readyState == 4){
	    
	    	// If it is succesful..
	    	if (Common.requestObject.status == 200) {
	    		// Do response function	
			Common.ajaxResponse();
			// Clear error function
			Common.ajaxError = false;
			
		} else {
			// If theres a custom erro function then do it
			if (Common.ajaxError) {
				Common.ajaxError();
			// Otherwise do default .....
			} else{ 
				alert("Sorry,there was an error processing you request.\nResponse code: " + Common.requestObject.status);
			}
		}
	
	    // If we are still waiting...
	    } else {
		Common.ajaxWait();
	    }
	},
	
	/**
	* Make an XML HTTP Request
	*
	* @param {String} url The url to request.
	* @param {Function} waitingFunction The function to perform whilst awaiting request.
	* @param {Function} responseFunction The function to perform on a succesful response.
	* @param {Function} errorFunction Optional. The function to perform on an unsuccesful request (IE: 404)
	*
	* @see #doAjaxResponse
	*/
	doAjaxSend : function(url, waitingFunction, responseFunction, errorFunction) {
		
		// Check we have capability
		if (!this.requestObject) return false;
		
		// Cache the functions
		this.ajaxWait = function(){waitingFunction()};
		this.ajaxResponse = function(){responseFunction()}; 
		if (errorFunction) this.ajaxError = function(){errorFunction()}; 
		
		// Send request, set onreadystatechange
		this.requestObject.open("GET", url, true);
		this.requestObject.onreadystatechange = this.doAjaxResponse;
		this.requestObject.send("");
	},
	
	
	/**
	* Fades an element. Changes CSS opacity over time.
	*
	* @param {Object} obj Element to apply fade to
	* @param {String} fadeType The type of fade, "in", "out", "blink"
	* @param {Integer} fadeSpeed Time in milliseconds for fade duration, this time is doubled for the blink type fade
	*/
	fade : function (obj, fadeType, fadeSpeed) {
	
		var speed = fadeSpeed / 10;
		
		// Store all fading elements in array, if over 100 start again.
		if (this.aLen >= 100) {
			this.aLen = 0;
		} else {
			this.aLen++;		
		}
	
		this.fadeElems[this.aLen] = obj;
		
		if (fadeType == "out")
			for (var i=0;i<11;i++) setTimeout('Common.setOpacity(Common.fadeElems['+this.aLen+'],'+(10-i)+')',speed*i);
		
		if (fadeType == "in")
			for (var i=0;i<11;i++) setTimeout('Common.setOpacity(Common.fadeElems['+this.aLen+'],'+i+')',speed*i);
		
		if (fadeType == "blink") {
			for (var i=0;i<11;i++) setTimeout('Common.setOpacity(Common.fadeElems['+this.aLen+'],'+(10-i)+')',speed*i);
			for (var i=0;i<11;i++) setTimeout('Common.setOpacity(Common.fadeElems['+this.aLen+'],'+i+')',speed*(i + 11));
		} 
		
		return false;
	},
	
	/**
	* Returns an array of requested elements of a particular class
	*
	* @param {String} searchClass The name of the required class.
	* @param {Object} oElm Optional. The HTML element in which to search.
	* @param {String} tag  Optional. The HTML tag that the class is applied to.
	*
	* @author http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
	*/
	getElementsByClass : function (oElm, strTagName, strClassName){
	
	    var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	    
	    var arrReturnElements = new Array();
	    
	    strClassName = strClassName.replace(/\-/g, "\\-");
	    
	    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
	    var oElement;
	    
	    for(var i=0; i<arrElements.length; i++){
		
		oElement = arrElements[i];
		
		if(oRegExp.test(oElement.className)){
		    arrReturnElements.push(oElement);
		}
		
	    }
	    
	    return (arrReturnElements)
	},

	/**
	* Returns an array of requested elements of a particular target
	*
	* @param {String} strTargetName The name of the required target.
	* @param {Object} oElm Optional. The HTML node in which to search.
	* @param {String} strTagName Optional. The HTML tag that the class is applied to.
	*
	* @author http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
	*/
	getElementsByTarget : function (oElm, strTagName, strTargetName){
	
	    var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	    
	    var arrReturnElements = new Array();
	    
	    strTargetName = strTargetName.replace(/\-/g, "\\-");
	    
	    var oRegExp = new RegExp("(^|\\s)" + strTargetName + "(\\s|$)");
	    var oElement;
	    
	    for(var i=0; i<arrElements.length; i++){
			
			oElement = arrElements[i];
			
			if(oRegExp.test(oElement.target)){
			    arrReturnElements.push(oElement);
			}
			
	    }
	    
	    return (arrReturnElements)
	},
	
	/**
	* Returns the value of a specified url parameter
	*
	* @param {String} name String. The name of the parameter to return the value for.
	* @param {String} url The URL to serach.
	*
	* @author http://www.netlobo.com/url_query_string_javascript.html
	*/
	getUrlParam : function(name, url) {
	
		var regexS = "[\\?&]"+name+"=([^&#]*)";
		var regex = new RegExp( regexS );
		var results = regex.exec(url);
		
		if(results == null)
			return "";
		else
			return results[1];
	},
	
	/**
	* Loads an external XML document and returns as a document object
	*
	* @param {String} feed Url of the xml document
	*/
	loadXML : function(feed) {
	
		// IE
		if (window.ActiveXObject) {

			var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async=false;
			xmlDoc.load(feed);
			
			return xmlDoc;

		// code for Mozilla, Firefox, Opera, etc.
		} else if (document.implementation && document.implementation.createDocument)	{

			var xmlDoc = document.implementation.createDocument("","",null);
			xmlDoc.async = false;
			
			try {
				xmlDoc.load(feed)
				return xmlDoc;
			} catch(e) {
				return false;;
			}
						
		} else {
		
			return false;
		}
	},
	
	
	/**
	* Returns a div with an id, can insert content too
	*
	* @param {String} divId The id to apply to the div
	* @param {String} Optional. The HTML content
	*
	*/
	makeDiv : function(divId, insides) {
		
		var tempDiv = document.createElement("div");
		tempDiv.id = divId;
		tempDiv.innerHTML = insides;
		return tempDiv;
	},	
	
	/**
	* Make a white transparent overlay div 
	*
	* @param {Object} obj Element to apply the overlay to, should be a positioned div. May work with other elements.
	* @param {String} overlayContains Optional. HTML to go inside the overlay div.
	*
	*/
	makeOverlay : function (obj, overlayContains) {
		
		// If overlay exists turn it on
		if(obj.hasOverlay) {
			Common.getElementsByClass(obj, "div", "overlay_div")[0].style.display = "block";
		} else {
			// It exists
			obj.hasOverlay = true;	

			// Build overlay
			if (overlayContains) {var inside = overlayContains;} else {var inside = ""};
			obj.innerHTML += "<div class=\"overlay_div\" style=\"position:absolute;top:0;left:0;z-index:10;width:100%;height:100%;background-color:#fff;opacity:0.75;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=75); \">"+inside+"</div>";
		}
	
	},		
	
	/**
	* Turns a pre existing overlay off (display = none);
	*
	* @param {Object} obj Element whose overaly to turn off.
	*
	*/
	makeOverlayInvisible : function (obj) {
		
		if (!obj.hasOverlay) return false;
		
		Common.getElementsByClass(obj, "div", "overlay_div")[0].style.display = "none";
	},
	
	/**
	* Sets an elements opacity style. In IE the opacity filter can only be applied to elements that have been styled with a width, height or position css attribute.
	*
	* @param {Object} obj Element to apply style rules to
	* @param {Integer} val Opacity range from 0 - 10
	*
	*/
	setOpacity : function(obj, val) {
		
		obj.style.opacity = val / 10;
		obj.style.filter = "alpha(opacity="+val*10+")";

	},
	
	/**
	* Applies options to an object
	*
	* @param {Object} opts The object holding the option properties and values
	*/
	setOptions : function(obj, opts) {
		for (var key in opts) {
			obj.options[key] = opts[key];
		}
	},

	/**
	* Applies CSS Rules to a HTML element
	*
	* @param {Object} obj The HTML element to which the styles will be applied.
	* @param {Object} styles The object holding the style properties and vlues.
	*/
	setStyles : function (obj, styles) {
		for (var i in styles) {
			obj.style[i] = styles[i];
		}
	},
	
	/**
	* Toggles an elements display CSS property.
	*
	* @param {Object} obj The HTML element to which the style will be applied.
	*/	
	
	toggle : function (obj) {

		obj.style.display != 'none' ? obj.style.display = 'none' : obj.style.display = '';
	},
	
	/**
	* Toggles an elements visibility CSS property.
	*
	* @param {Object} obj - The HTML element to which the style will be applied.
	*/	
	
	toggleVis : function (obj) {
	
		obj.style.visibility != 'hidden' ? obj.style.visibility = 'hidden' : obj.style.visibility = 'visible';
	},
	
	/**
	* Trims a string to required length. Can append a string on the end
	*
	* @param {String} string The string to be trimmed.
	* @param {Integer} len The max length to trim the string to.
	* @param {String} append Optional. The string to be appanded on the end.
	* @param {Boolean} nearestWord Optional. Whether to trim to the nearest word under the specified length.
	*
	*/
	trimString : function (string, len, append, nearestWord) {
	
		// Trim to length
		var thisStr = string.substring(0, len);
	
		// If nearestWord then recurse through function and trim to the nearest word under the specified length
		if(thisStr.substring(len -1, len) != ' ' && nearestWord) {
			thisStr = Common.trimString(thisStr, len - 1, null, true);			
		}
		
		// If append
		if (append) {
			// Take off last space if 
			if (nearestWord) thisStr = thisStr.substring(0, (thisStr.length -1));
			// Append
			thisStr += append;
		}
		
		// Return trimmed string
		return thisStr;
	}

}


/**
 * Add Array push method, because some browsers like IE 5 don't have them 
 * @addon
 */

Array.prototype.push = function() {
    var n = this.length >>> 0;
    for (var i = 0; i < arguments.length; i++) {
        this[n] = arguments[i];
        n = n + 1 >>> 0;
    }
    this.length = n;
    return n;
};

/**
 * Add Array pop method, because some browsers like IE 5 don't have them 
 * @addon
 */
Array.prototype.pop = function() {
    var n = this.length >>> 0, value;
    if (n) {
        value = this[--n];
        delete this[n];
    }
    this.length = n;
    return value;
};

Common = new Common();
