/*
	$Id: ads.js,v 1.73 2009/10/14 10:54:15 ortizr Exp $
*/
var clientAds = new Ads(); // array of all deferred ads on the page, gets initalised when new Ads() called for the first time.
//clientAds.renderOneByOne = false;
thisPage.delayAdRender = (typeof document.getElementById != UNDEFINED || typeof document.createElement != UNDEFINED) ? true : false;
thisPage.delayAdRender = (is.mac && is.ie) ? false : true;
thisPage.delayAdRender = (is.ie5 && !is.ie5_5) ? false : true;
//when included ads aren't downloading
//thisPage.delayAdRender = (is.opera) ? false : true;
//thisPage.delayAdRender = false;

/* Advert div id prefixes */
var AD_CONTAINER_PREFIX = "ad-container-";
var AD_PLACEHOLDER_PREFIX = "ad-placeholder-";

/* Advert type constants */

/*new ad for Macro Maps pages  */
var AD_MACROAD = "macroad";     // Macro Ad 120x60

/*new current falcon ads */
var AD_NEWSSUBS = "newssubs";
var AD_MARKETINGRIB = "marketingrib";
var AD_TLBXRIB = "tlbxrib";
var AD_INTRO = "intro";
var AD_HLFMPU = "hlfmpu";
var AD_HMMPU = "hmmpu";
var AD_TRADCENT = "tradcent";
var AD_MARKETING = "marketing";
var AD_DOUBLET = "doublet";

/* Display Adverts */
var AD_BANLB = "banlb";   		// Banner/Leaderboard 		468x60 or 728x90, collapsable
var AD_MPUSKY = "mpusky"; 		// AD_MPU Box/Sky				300x250, 336x280, 160x600, 120x600, collapsible
var AD_MPU = "mpu"; 			// AD_MPU Box					300x250 or 336x280, not collapsible
var AD_WDESKY = "wdesky"; 		// Sky/Wide Sky
var AD_NRWSKY = "nrwsky";		// Narrow skyscraper only	120x600, non-collapsible				
var AD_ARTBOX = "artbox";		// 180x150 Article Box
var AD_OOB = "oob";			// Out of Banner
var AD_FTHBOX = "fthbox"; 		// Fourth Column Box
var AD_ALPLIVP = "alplivp"; // Alphaville ad

/* Sponsorship only Ad units */
var AD_TLBX = "tlbx";			// Tool Box
var AD_LHN = "lhn";			// Left Hand Nav Sky
var AD_DSKALERT = "dskalert";	// Desktop Alert
var AD_FMBUT2 = "fmbut2";		// Clickablity
var AD_QWS = "qws";			// Investor Relations Button

/* Market / filler only Ad units */
var AD_MKTBX = "mktbx";		// AD_LHN Marketing Box
var AD_POP = "popp";			// Pop Up/Under. Note "pop" is a keyword in JavaScript, so we can't use it, but can map popp->pop later on in the ad call
var AD_BXBAR = "bxbar";
var AD_DKTALRT = "dktalrt";
var AD_DSKTICK = "dsktick";
var AD_PRNT = "prnt";
var AD_INV = "inv";
var AD_MBATOP = "mbatop";
var AD_MBABOT = "mbabot";
var AD_MBALINK = "mbalink";
var AD_SBHEAD = "sbhead";
var AD_FTNT = "ftnt";
var AD_1x1 = "1x1";
var AD_CURRCON = "currcon";
var AD_CURRBOX = "currbox";
var AD_CORPPOP = "corppop";

/* UTILITY FUNCTIONS */

function isSecure(doc){
    return (doc.location.protocol=='https:');
}
var TEMPHTTP = isSecure(document)?'https':'http';

/*	
	Page-level properties affecting all ads
	renderOneByOne 				- true: render (move) each deferred ad straight after it is fetched,
								  false: render (move) all ads together after they have all been fetched
	preloadDefaultText
	captionDefaultText
	placeHolderErrorDefaultText
*/

function Ads(){
	this.obj ="AdsObject";
	eval(this.obj + "=this");
	// private attributes
	var ads = new Array;
	var renderOneByOne = false;
	var preloadDefaultText = "Loading advertisement...";
	var captionDefaultText = "Advertisement";
	var placeHolderErrorDefaultText = "Cannot load advertisement";
	var displayIfOutsizedtDefaultText = "Advertisement too large to be displayed";
	this.fetch=function(pos) {
		var ad;
		for (a in ads) {
			if (a==pos)	{
				ad=ads[a];
				break;
			}
		}

	/* If the Ad position is a corporate sign up popup, it is only to be fetched if there is a non empty parameter _27 in the AYSC cookie */
	var tempAYSC = getCookieValue('AYSC', '');
	var cookieValue = getValueFromStr('_27', '', tempAYSC, '_', '');
	if ( ( cookieValue == "NULL" || cookieValue == "PVT" || cookieValue === "" ) && pos == "corppop" ) {
		return;
	} else {	
			if(ad && !ad.getFetched() && ad.isFetchable() ) {
				if(TEMPHTTP == "https"){
					return;
				}
				document.write(ad.getAdHTML());
				ad.setFetched(true); // never fetch an ad more than once
			}
		}
	};	
	this.render = function(pos) {

	   /* collapse leaderboard when target banner name is 'suppressed leaderboard'
	    done via AdMan. Also you can drop variable collapseThisBanner
	   */
      if (typeof banlbAd != UNDEFINED && (pos == 'banlb' || pos == 'newssubs')) {
            if (banlbAd.getName() == 'suppressed leaderboard'){
				  document.getElementById("leaderboard").style.display = 'none';
				  document.getElementById("leaderboard").style.height = '0px';
            }
		    return;	
      }
		if (pos && 	renderOneByOne) {
			doRender(ads[pos]);
		} else if (!pos && !renderOneByOne) {
			for (var adPos in ads) {
				doRender(ads[adPos]);
			}
		}
	};

	/* Private method to add an Advert object into clientAds. */
	this.add = function(ad) {
		var pos = ad.getPosition();
		if (ads[pos]){
			//thisPage.err("Duplicate ad pos '"+pos+"' on page");
		} else {
			ads[pos]=ad;
		}
		return ad;
	};

	function doRender(ad){
		if(ad && ad.isRenderable()) {
			var sourceDiv = document.getElementById(ad.getSourceDiv());
			var targetDiv = document.getElementById(ad.getTargetDiv());
		if(TEMPHTTP == "https"){
			targetDiv.style.display='none';
			return;
		}
			if(sourceDiv && targetDiv && !ad.getRendered()) {
				sourceDiv.style.display="inline"; //block screws up IE
				var captionPara = document.createElement("p");
				var caption = ad.getShowCaption();
				if (captionPara) {
					if (caption===true) {
						caption = captionDefaultText;
					}
					captionPara.innerHTML = (caption);
				}
				if(!ad.getTrueWidth()) {ad.setTrueWidth(ad.calculateTrueWidth());}
				if(!ad.getTrueHeight()) {ad.setTrueHeight=(ad.calculateTrueWidth());}
				var tw = ad.getTrueWidth();
				var th = ad.getTrueHeight();
				if(ad.getDisplayIfOutsized() && ad.isExist() ) {	
					moveSourceToTarget(sourceDiv,targetDiv);
					if(caption.length>0) {
						targetDiv.appendChild(captionPara); // using targetDiv.appendChild here breaks Opera8, maybe use sourceDiv?
					}
				} else 	if (!ad.getDisplayIfOutsized() && ad.isExist() ) {
					var hintWidth = ad.getHintWidth();
					var hintHeight = ad.getHintHeight();
					// If the targetDiv has specific width and height (not auto) and the
					// ad dimensions blow this, then don't display.
					var tolerance = 0.05; // 5% tolerance to allow for div padding in IE
					tolWidth = hintWidth*(1+tolerance);
					tolHeight = hintHeight*(1+tolerance);
					if ( (!tolWidth || tolWidth && tw<=tolWidth) && (!tolHeight  || tolHeight && th<=tolHeight) ) {				
						targetDiv.innerHTML="";	
						moveSourceToTarget(sourceDiv,targetDiv);
						//captionPara.innerHTML += " " + ad.getPosition();
						if (caption.length>0) {
							setTimeout(function(){targetDiv.appendChild(captionPara);},1); // caption to appear below ad, needs setTimeout
						}
						var marLeft = (targetDiv.offsetWidth-tw)/2;
						var marTop = (targetDiv.offsetHeight-th)/2;
						if (marLeft>0) {						
							//sourceDiv.style.marginLeft = (targetDiv.offsetWidth-tw)/2 + "px";
						}
						if (marTop>0) {
							//sourceDiv.style.marginTop = (targetDiv.offsetHeight-th)/2 + "px";
						}
						var shiftDiv = document.getElementById("ad-shiftholder-" + ad.getPosition());
						var doShift = ad.getPosition()=="mpusky" && targetDiv.offsetWidth>180;  //currently only interested in the mpusky box version of the ad
						if(shiftDiv && doShift) {
							var shiftBy = shiftDiv.offsetTop-targetDiv.offsetTop;
							if(shiftBy>0) {
								if(is.ie) {
									// IE6 bug duplicates GET request if not in onload
									targetDiv.style.display="none";
									attachOnload("var td=document.getElementById('"+targetDiv.id+"');document.getElementById('"+shiftDiv.id+"').insertBefore(td);td.style.display='block'");
								} else {
									shiftDiv.appendChild(targetDiv);
								}
							}
						}
					} else {
						var theSrc = ad.getAdHTML().match(/src=(.*)/);
						theSrc = RegExp.$1.replace(/=/," ");
						theSrc="";
						showError(displayIfOutsizedtDefaultText + " (" + tw + "x" + th + " should be " + hintWidth + "x" + hintHeight +" max.)" + "<br/>" +  theSrc );
					}
				} else {
					showError(placeHolderErrorDefaultText);
				}
				ad.setRendered(true);
			}
		}

		function moveSourceToTarget(s,t) {
				var txt = false;
				if (document.getElementById("right-rail")) {
					//need to be hidden and then displayed for ie bug when no ad is present - so that if no ad can be hidden	
					document.getElementById(t.id).style.display ="block";
					if (s.offsetHeight < 10) {
						//tg	document.getElementById(t.id).style.display ="none";
					}
				}
				var divvy=document.createElement("div");
				//tg	divvy.style.position="relative";
				//tg	divvy.style.height=s.offsetHeight + "px";
				//tg	divvy.style.width=s.offsetWidth + "px";
				if (document.getElementById("right-rail") && document.getElementById("ad-placeholder-banlb") && typeof (AdHeight_banlb) != "undefined"  && (AdHeight_banlb < "90")){
					document.getElementById("ad-placeholder-banlb").style.margin="15px 8px 0 10px";
					document.getElementById("ad-placeholder-banlb").style.height="60px";
					if (is.ie6){
						document.getElementById("ad-placeholder-banlb").style.margin="15px -2px 0 10px";
					}
				}	
				if(document.getElementById("ad-placeholder-banlb")){document.getElementById("ad-placeholder-banlb").style.display ="block";}
				if (document.getElementById("right-rail") && (t.id !="ad-placeholder-newssubs") && (t.id !="ad-placeholder-banlb") && s.offsetHeight > 0){				
					divvy.style.marginBottom="15px"
						if (s.offsetWidth < 336 && (t.id !="ad-placeholder-marketing") && (t.id !="ad-placeholder-tlbx")){
							divvy.style.padding="14px 0 14px 0";
							//divvy.style.border="solid 1px #999";
							divvy.style.width= "334px";	
						}
						//divvy width is 4 pixels wider than image - in ie causes a problem so width fixed at 336.
						if (s.offsetWidth > 336 && is.ie6){
							divvy.style.width= "336px";
						}
						if (s.id =="ad-container-tlbx"){
							for (i=0;i<s.childNodes.length;i++){
								if(s.childNodes[i].className == "rhc-con rhc-con-sm"){
									txt = true;	
									i++	
								}
							}
							if (txt == false){
									divvy.style.padding="11px 0 11px 0";	
									divvy.style.height= "125px";
									divvy.style.border="solid 1px #999";
									divvy.style.width= "162px";	
								}
						}
						if (s.id =="ad-container-marketing"){
							for (i=0;i<s.childNodes.length;i++){
								if(s.childNodes[i].className == "rhc-con rhc-con-sm"){
									txt = true;	
									i++	
								}
							}
							if (txt == false){
									divvy.style.padding="11px 0 11px 0";	
									divvy.style.height= "125px";
									divvy.style.border="solid 1px #999";
									divvy.style.width= "162px";	
							}
					}
				}	
				if (!document.getElementById("right-rail")){
					if(!is.ie) {
						var indent = (t.offsetWidth-s.offsetWidth)/2;
						divvy.style.left = (indent>0?indent:0) + "px";
					}
					s.style.position="absolute";
				}
				else
				{
					var x,cnc = s.childNodes.length;
					for ( x=0;x<cnc;x++)
					{
						if ( s.childNodes[ x ].tagName == "SCRIPT" || s.childNodes[ x ].tagName == "script"  )
						{
							s.childNodes[ x ].src="http://ads.ft.com/null_ad.js";
							s.childNodes[ x ].type="text/html";
						};
					};
					if(t.id !="ad-placeholder-banlb") divvy.appendChild( s);
				}; //tg This else was added in to position the ads in their correct location on screen
				t.appendChild(divvy);
				//tg	s.style.position="absolute";
				//tg	s.style.display="block";
				//tg	s.style.left=getElementLeft(divvy) + "px";
				//tg	s.style.top=getElementTop(divvy) + "px";
				if (document.getElementById("right-rail") && (t.id !="ad-placeholder-newssubs") && (t.id !="ad-placeholder-banlb") && s.offsetHeight > 0){
					if (s.offsetWidth < 336 && (t.id !="ad-placeholder-marketing") && (t.id !="ad-placeholder-tlbx")){
					s.style.top=getElementTop(divvy) + 15 + "px";				
					s.style.paddingLeft = ("336" - s.offsetWidth) /2 + "px";
					}
					if (t.id =="ad-placeholder-marketing" || t.id =="ad-placeholder-tlbx"){
						if (txt == false){
							s.style.top=getElementTop(divvy) + 12 + "px";
							s.style.paddingLeft = ("167" - s.offsetWidth) /2 + "px";
						}	
					}
				}	
			var elem =  document.getElementById("ad-container-hlfmpu");
			if (elem && elem.style)
			{
				elem.style.paddingLeft="0";
				elem.style.marginLeft="0";
			}
			var elem =  document.getElementById("ad-placeholder-doublet");
			if (elem && elem.childNodes && elem.childNodes.length)
			{
				elem.childNodes[0].style.width="100%";
			};	
		}

		function showError(msg) {
			// TODO: extend this for Ash to log error into ad instance for interrogation/loggin by JavaScript
			var error = ad.getShowPlaceholderOnError();
			if(error==true) {
				error = msg;
			}

			/* IE6 GET requests the ad again if removeChild is used! */
			if(error.length>0) {
				var para = document.createElement("p");
				para.innerHTML=error;
				para.style.marginTop=targetDiv.offsetHeight/3 +"px";
				targetDiv.innerHTML="";
				targetDiv.appendChild(para);
				sourceDiv.innerHTML="";
			} else {
				sourceDiv.innerHTML="";
				targetDiv.innerHTML="";
			}
		}
	}
	this.renderPlaceholder = function(ad) {
		var targetDiv = document.getElementById(ad.getTargetDiv());
		if (targetDiv) {
			var preload = ad.getShowPreload();
			if(preload==true) {
				preload=preloadDefaultText;
			}
			if(preload.length>0)	{
				var para = document.createElement("p");
				para.setAttribute(CLASS,"loader");
				para.innerHTML=preload;
				para.style.marginTop=targetDiv.offsetHeight/3 +"px";
				targetDiv.innerHTML="";
				targetDiv.appendChild(para);
			}
		}
	}
	this.setRenderOneByOne = function(val) {renderOneByOne = val;}
	this.debug = function() {
		var ad, str = "";
		for (var a in ads) {
			if ( ads.hasOwnProperty( a ) )
			{
				ad = ads[a];
				str += ("\n\n===================================" +
					"\nAdvert: " + ad.getPosition() +
					(ad.isLegacy()?"\nTHIS AD IS FROM A LEGACY AD CALL!":"") +
					"\nid: " + ad.getId() +
					"\nname: " + ad.getName() +
					"\nflightId: " + ad.getFlightId() +
					"\nwrap: " + wrap +
					"\ntrueWidth: "  + ad.getTrueWidth() +
					"\ntrueHeight: " + ad.getTrueHeight() +
					"\n===================================");
			}
		}
		return(str);
	};
	this.getAdByPosition = function(pos) {
		for(a in ads) {
			if (a = pos) {
				return ads[a];
			}
		}
	};
};

/*	
	Individual Ad  properties
	renderImmediately 			- [ true  | false* ] render immediately inline, or fetch and render ad at the bottom of the page
	showPreloadText 			- [ true  | false* | string] show preload text whilst ad is loading (deferred mode only?)
	showCaption 				- [ true* | false  | string] show caption text below ad if true
	removePlaceHolderOnError	- [ true  | false* | string]  custom string can be used, if false then remove placeholder altogether
	displayIfOutsized			- [ true  | false* ]
*/

function Advert(pos){
	// Private attributes
	var sourceDiv;// = AD_CONTAINER_PREFIX + pos;		// default to the same div id suffix as the advert position, can override if you really want to
	var targetDiv;// = AD_PLACEHOLDER_PREFIX + pos;	// default to the same div id suffix as the advert position, can override if you really want to
	var position = pos;								// ad position
	var type = pos;										// ad type to get from the ad server (1:n type:position)
	var fetched = false;							// has the ad been fetched from the server?
	var rendered = false;							// has the ad already been rendered?
	var initialLength = 0;
	// display defaults
	var renderImmediately = false;
	var showPreload = false;
	var showCaption = false;
	var showPlaceholderOnError = false;
	var displayIfOutsized = false;
	var fetchable = true; // masthead ad may get semi-initalised if logged-in, but we don't want to fetch or render it.
	var renderable = true;
	var hintWidth=null;
	var hintHeight=null;

	/* Properties that will usuall get set by ad server */
	var id=null;
	var name=null;
	var flightId=null;
	var trueWidth=null;
	var trueHeight=null;
	//var wrap=null;
	var allParams=null;
	var isExist=false;
	// legacy ad call support
	this.adHTML = "";
	var isLegacy = (arguments.length>1)?true:false;

	function setDisplayDefaults(_renderImmediately, _showPreload, _showCaption, _showPlaceholderOnError, _displayIfOutsized) {
		renderImmediately = _renderImmediately;
		showPreload = _showPreload;
		showCaption = _showCaption;
		showPlaceholderOnError = _showPlaceholderOnError;
		displayIfOutsized = _displayIfOutsized;
	}

	function setDimensionHints(_hintWidth, _hintHeight) {
		hintWidth = _hintWidth;
		hintHeight = _hintHeight;
	}

	/* Initalise the advert after you've constructed and also overridden any properties you want */
	this.init = function() {		
		sourceDiv = AD_CONTAINER_PREFIX + position;		// default to the same div id suffix as the advert position, can override if you really want to
		targetDiv = AD_PLACEHOLDER_PREFIX + position;	// default to the same div id suffix as the advert position, can override if you really want to
		//clientAds.add(this); // add this Advert into the deferred loading array
		if ( !thisPage.delayAdRender || this.getRenderImmediately() ) {
				//this.getAdHTML();
				// render straight away
				clientAds.fetch(this.getPosition());
				this.setRendered(true);
			} else {			
				clientAds.renderPlaceholder(this); // render the placeholder div (the full advert render and move will be handled automatically at the bottom of the page)
		}
	}

	/* Get the full ad html to be written to the page.
		[pos]		ad position	(ad object)
		[14]		country: reg form if available, else traceware (cookie)
		[Wrap]		editorial wrap: wrap (returned ad javscript from a previous ad)
		[ind]		FT CC3 Industry
		[artid]		FT CC3 Page
		[sec]		FT CC3 Section
		[keyword]	Keyword
		[leaderServed]	declares banlb on the page: leaderserved (returned ad javscript from banlb ad)
		[18]		Metro
		[asset]		Page asset
		[referrer]	Referrer (put at end, escape) (document.referrer)
		[17]		Region
		[rsi]		Revenue Science Segment (thisPage.revScience)
		[site]		Site
		[ftfund]	FT Funds
		http/s
		yahoo
		thisPage.alladparams
		params.styles (not needed?)
	*/
	this.getAdHTML = function() {
		var adHTML = '';
		//var style = "collapse,html";
		var style = "";
		var pos = type;
		var adStyle = style ? "&params.styles=" + style : '';
		//var wrap =  this.getWrap();
		//var adWrap = wrap&&wrap!= null?'&wrap=' + this.getWrap():'';
		var adWrap = wrap != ''?'&wrap=' + wrap:'';
		var leaderServed = leaderserved != ''?'&leaderserved=' + leaderserved:'';
		var siteName='ftcom';
		if (thisPage.ftsite == 'yahoo1') {
			if (pos == 'banlb' || pos =='mpusky') {
				siteName = thisPage.ftsite;
			}
		}
		
		var asset = "&asset=" + thisPage.asset;
		var referrer =  "&referrer=" + document.referrer;
		var revSci = thisPage.revScienceFull ;
		
		allParams = "site=" + siteName + "&pos=" + pos + thisPage.alladparams + adWrap + leaderServed + revSci+ adStyle + asset + referrer; // +divId +adLink+nextAd;
		
		 if  (allParams.length > 1000) {
			//remove the referrer, see if that helps
			allParams = "site=" + siteName + "&pos=" + pos + thisPage.alladparams + adWrap + leaderServed + revSci+ adStyle + asset; 
			
			// still too long?
			if (allParams.length > 1000) {				
			    var chopOff = allParams.length-1000;
			    // reduce the string and remove the last value as is may be only a partial value
			    revSci = revSci.substring(0,revSci.length-chopOff).split(",").slice(0,-1).join(",") + ",";		
			    allParams = "site=" + siteName + "&pos=" + pos + thisPage.alladparams + adWrap + leaderServed + revSci+ adStyle + asset; 	   			   
			}
		
		}
		
		var adsDom = 'http://ads.ft.com';
		if (thisPage.issec) {
			adsDom = 'https://secureads.ft.com';
		}
		if (!is.nav4 && (!is.opera5 && !is.opera6)) {
			adHTML += '<scr'+'ipt src="'+adsDom+'/js.ng/'+allParams+'"></scr'+'ipt>\n';
		} else {
			adHTML += '<a href="'+adsDom+'/click.ng/'+allParams+'" target="_blank">';
			adHTML += '<img src="'+adsDom+'/image.ng/'+allParams+'" border="0" alt="Advertisement" /></a>';
		}
		return adHTML;
	}

	/* Does the fetched ad exist - i.e. has the call to the ad server returned anything? */

	/* Not working in IE */

	/*this.isExist = function() {
		var srcDiv = document.getElementById(sourceDiv);
		var allEls = srcDiv.childNodes;
		var maxWidth=0;
		for (var i=0;i<allEls.length;i++) {
			if(allEls[i].offsetWidth) {
				maxWidth=Math.max(maxWidth,allEls[i].offsetWidth);
			}
		}
		return maxWidth>0;
	}*/

	/* Get the actual width of the fetched ad, i.e.
	   the ad exists if > 0.  This allows the placeholder to have a
	   CSS width (for layout).
	 */	
	this.calculateTrueWidth = function() {
		var srcDiv = document.getElementById(sourceDiv);
		// Can't do this becasue some ads contain (e.g.) an absolute div element
		// with width and height set to the full screen size - this routine takes the
		// element into account and blows the width/height.
		var allEls = srcDiv.childNodes;
		var maxWidth=0;
		for (var i=0;i<allEls.length;i++) {
			//alert(pos + ": " + allEls[i].style.width + "\ndisplay: " + allEls[i].style.display + "\nvisibility: " + allEls[i].style.visibility + "\nwidth: " + allEls[i].getAttribute("width") + "\nposition: " + allEls[i].style.position)			
			if(allEls[i].offsetWidth && (allEls[i].style && allEls[i].style.position!="absolute")) {
				//alert("maxWidth: " + maxWidth + "\nallEls[i].offsetWidth: " + allEls[i].offsetWidth)
				maxWidth=Math.max(maxWidth,allEls[i].offsetWidth);
			}
		}
		maxWidth=Math.max(maxWidth,srcDiv.offsetWidth);
		return maxWidth;
	}
	this.calculateTrueHeight = function() {
		var srcDiv = document.getElementById(sourceDiv);
		// Can't do this becasue some ads contain (e.g.) an absolute div element
		// with width and height set to the full screen size - this routine takes the
		// element into account and blows the width/height.
		var allEls = srcDiv.childNodes;
		var maxHeight=0;
		//alert(this.getPosition() + " " + allEls[i] + ": " + allEls[i].offsetHeight + "max: " + Math.max(maxHeight,allEls[i].offsetHeight));		
		for (var i=0;i<allEls.length;i++) {
			if(allEls[i].offsetHeight && (allEls[i].style && allEls[i].style.position!="absolute")) {
				//alert("maxHeight: " + maxHeight + "\nallEls[i].offsetHeight: " + allEls[i].offsetHeight)
				maxHeight=Math.max(maxHeight,allEls[i].offsetHeight);
			}
		}
		maxHeight=Math.max(maxHeight,srcDiv.offsetHeight); //Mozilla
		//maxHeight = srcDiv.offsetHeight
		return maxHeight;
	}
	// Getters and setters
	this.getRenderImmediately = function() {return renderImmediately;}
	this.setRenderImmediately = function(val) {renderImmediately = val;}
	this.getShowPreload = function() {return showPreload;}
	this.setShowPreload = function(val) {showPreload = val;}
	this.getShowCaption = function() {return showCaption;}
	this.setShowCaption = function(val) {showCaption = val;}
	this.getShowPlaceholderOnError = function() {return showPlaceholderOnError;}
	this.setShowPlaceholderOnError = function(val) {showPlaceholderOnError = val;}
	this.getDisplayIfOutsized = function() {return displayIfOutsized;}
	this.setDisplayIfOutsized = function(val) {displayIfOutsized = val;}
	this.setSourceDiv = function(val) { sourceDiv = AD_CONTAINER_PREFIX + val; }
	this.getSourceDiv = function() { return sourceDiv; }
	this.setTargetDiv = function(val) { targetDiv = AD_PLACEHOLDER_PREFIX + val; }
	this.getTargetDiv = function() { return targetDiv; }
	this.setPosition = function(val) { position = val; }
	this.getPosition = function() { return position; }
	this.setFetched = function(val) { fetched = val; }
	this.getFetched = function() { return fetched; }
	this.setRendered = function(val) { rendered = val; }
	this.getRendered = function() { return rendered; }
	this.getHintWidth = function() { return hintWidth; }
	this.setHintWidth = function(val) { hintWidth=val; }
	this.getHintHeight = function() { return hintHeight; }
	this.setHintHeight = function(val) { hintHeight=val; }
	this.isFetchable = function() { return fetchable; }
	this.setFetchable = function(val) { fetchable=val; }
	this.isRenderable = function() { return renderable; }
	this.setRenderable = function(val) { renderable=val; }

	/* Set by the ads team to the actual width and height of the ad being returned */
	this.setTrueWidth = function (val) {trueWidth = val;}
	this.getTrueWidth = function (val) {return trueWidth;}
	this.setTrueHeight = function (val) {trueHeight = val;}
	this.getTrueHeight = function (val) {return trueHeight;}

	/*this.setWrap = function (val) {wrap = val;}
	this.getWrap = function (val) {return wrap;}
	*/
	this.setAllParams = function (val) {allParams = val;}
	this.getAllParams = function (val) {return allParams;}
	this.setId = function (val) {id = val;}
	this.getId = function (val) {return id;}
	this.setName = function (val) {name = val;}
	this.getName = function (val) {return name;}
	this.setFlightId = function (val) {flightId = val;}
	this.getFlightId = function (val) {return flightId;}
	this.setExist = function(val) {isExist=val;}
	this.isExist = function() {return isExist;}
	this.setLegacy = function(val) {isLegacy=val;}
	this.isLegacy = function() {return isLegacy;}
	//TODO: returned ad if blank contains a 1x1 pix gif, might need to extend the checking to exclude this if it's returned (thus that's a non-ad).

	/* Set defaults for some known ad types.  Note these can be overridden in the HTML, so if
	   the ad is behaving strangely, check any overrides the developer may have put in place.
	   These must be initalised outside the init() call.
	 */
	switch(position) {

	case AD_MACROAD:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(120,60);
		break;

	case AD_NEWSSUBS:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(240,90);
		break;

	case AD_MARKETINGRIB:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(336,60);
		break;

	case AD_TLBXRIB:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(336,60);
		break;

	case AD_INTRO:
			setDisplayDefaults(true,false,false,false,true);			
			setDimensionHints(1,1);
		break;

	case AD_HLFMPU:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(336,850);
		break;

	case AD_HMMPU:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(336,280);
		break;

	case AD_TRADCENT:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(336,280);
		break;

	case AD_MARKETING:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(125,125);
		break;

		case AD_BANLB:
			setDisplayDefaults(true,false,false,false,false);			
			setDimensionHints(728,90);
		break;

		case AD_MPUSKY:
			setDisplayDefaults(false,false,true,false,false);			
			setDimensionHints(336,600);
		break;

		case AD_MPU:
			setDisplayDefaults(true,true,false,false,false); //changed this to always be collapsible - also changed to load inline
			setDimensionHints(336,280);
		break;

		case AD_WDESKY:
			setDisplayDefaults(false,true,false,false,false);			
			setDimensionHints(160,600);
		break;

		case AD_NRWSKY:
			setDisplayDefaults(false,true,false,false,false);			
			setDimensionHints(120,600);
		break;

		case AD_ARTBOX:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(180,150);
		break;

		case AD_OOB:
			setDisplayDefaults(false,false,false,false,true);
			setDimensionHints(1,1);
		break;

		case AD_FTHBOX:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(192,73);
		break;

		case AD_TLBX:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(134,124);
		break;

		case AD_LHN:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(139,null); // different sizes ..???
		break;

		case AD_DSKALERT:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(234,60);
		break;

		case AD_FMBUT2:
			setDisplayDefaults(true,false,false,false,false);			
			setDimensionHints(445,25);
		break;

		case AD_QWS:
			setDisplayDefaults(false,false,false,false,false);			
			setDimensionHints(500,500); // ???
		break;

		case AD_MKTBX:
			setDisplayDefaults(false,false,false,false,false);	
			setDimensionHints(139,null);
			//setDimensionHints(500,500); // ???
		break;

		case AD_POP:
			setDisplayDefaults(false,false,false,false,false);
			//type="pop"; // because we can't use 'pop' in the hashtable since it's a reserved word.
			//setDimensionHints(300,300);
		break;	

		case AD_BXBAR:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(336,280);
		break;

		case AD_DKTALRT:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(234,60);
		break;

		case AD_DSKTICK:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(120,20);
		break;

		case AD_PRNT:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(445,25);
		break;

		case AD_INV:
			setDisplayDefaults(false,true,false,false,false);	
		break;		

		case AD_MBATOP:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(445,25);
		break;

		case AD_MBABOT:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(445,25);
		break;		

		case AD_MBALINK:
			setDisplayDefaults(false,true,false,false,false);	
		break;

		case AD_SBHEAD:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(234,60);
		break;		

		case AD_FTNT:
			setDisplayDefaults(false,true,false,false,false);	
		break;

		case AD_1x1:
			setDisplayDefaults(false,true,false,false,false);	
			setDimensionHints(1,1);
		break;

		case AD_ALPLIVP:
			setDisplayDefaults(false,true,false,false,false); //changed this to always be collapsible - also changed to load inline. - Emergency fix to move into deferred loading.
			setDimensionHints(336,280);
		break;

		case AD_DOUBLET:
  			setDisplayDefaults(false,false,false,false,false);
		break;

		case AD_CURRCON:
  			setDisplayDefaults(true,true,false,false,false);
  			setDimensionHints(120,60);
		break;

		case AD_CURRBOX:
                        setDisplayDefaults(true,true,false,false,false);
                        setDimensionHints(120,60);
                break;

		case AD_CORPPOP:
                        setDisplayDefaults(false,false,false,false,false);
		break;
	}
	this.adHTML=this.getAdHTML(); // legacy support - stick the ad code in a public variable for direct access with document.write
	clientAds.add(this);
}

function randomValue(low, high) {
	return Math.floor(Math.random() * (1 + high - low) + low);
}
