/* Copyright 2006 Yahoo Inc. All rights reserved. */

// the documentation is in [markdown](http://daringfireball.net/projects/markdown/syntax) and should be kept in sync with the source code.  The documentation comment must start and end with @doc

/* @doc

# YAHOO.ads.darla

Support library for ad-fetching and display, including timer-based event management.

## methods

-	`setConfig(config, initialState)`

	Specify the configuration object for the library.

	`installState` defines the initial ad-fetching state, either 1 (which is the default value and calls ads immediately upon the first event) or 0 (pretend ads have been fetched and start the display timer - useful when the first batch of ads have already come down with the page)

	`config` is a object describing ad calls and behavior, with any of the following properties set:

	-	`callFrame`
	
		Default value: `"fccall"`
		
		The id of the iframe into which to load `callScript`. This iframe must already exist in the document.

	-	`callScript`
	
		Default value: "fc.php"
		
		The full url to the fc.php script.  

	-	`rotation`

	  	Default value: 5000

		If auto rotation is on, this number of milliseconds between the last ad rotation and the next ad rotation, provided there was a user event of some kind in the time period before next ad rotation as specified by `autoRotationWindow`, below.

		If auto rotation is off, this is the milliseconds to wait after an ad rotation before the next user event can trigger an ad call (so, in practice the actual rotation is a little bit longer than this interval)
	
	-	`autoRotation`
	
	  	Default value: `false` 

		If `true`, automatically rotate ads according to the setting of rotation

	-	`property`
	
	  	Default value: `"yahoo"`

		Each call to ad server requires a space id, location/position, and short property name as indicated by this variable.  Clients should set this variable to the name RUBY uses to identify their property

	-	`encoding`
	
	  	Default value: `"utf-8"`

		The expected charset encoding of data in the ad system.

	-	`simpleTemplate`
	
	  	undefined by default

		 A string representing the html that will be written into an ad destination element (these elements are defined as values in `destinationMap`) if no template is defined for that element in templates

		 The default value for this is:
		
			"<html><head>" +
			"<!--ENCODING--><base target='_blank' />" +
			"<!--STYLE--></head><" +
			"body style='overflow:hidden;'>" +
			"<table width='100%' height='100%'><tr>" +
			"<td align=center valign=top>" +
			"<!--ADHTML--></td></tr></table>" +
			"</body></html>"

	-	`destinationMap`
	
		undefined by default
	
		When setting up the configuration object, you must provide this as an object which maps `adPosition` to `destinationElement`.  For instance, in the bardtest, this is defined as

			{
				"SKY":	"SKY",
				"LREC": "LREC",
				"W1":	"W1",
				"MNW":	"MNW",
				"SW1":	"SW",
				"SW2":	"SW",
				"SW3":	"SW",
				"FB2":	[ "FB1", "FB2", "FB3" ]
			}
			
		NOTE: if using the same iframe for both the Darla PHP code and an ad, then that ad position MUST NOT be included in `destinationMap`
	
	-	`templates`
	
		undefined by default

		A template may be defined for each ad-containing element (the `simpleTemplate` will be used if no such definition is provided).  You should set this to an object mapping such templates.  In bardtest, this is set to:

			{
				"MNW": "<div id='nwPane' style='width:100%'><div id='MNW'><!--MNW--></div></div>",
				"SW": "<div id='swPane' style='width: 100%;'>" +
				     "<div id='SW1' class='first'><!--SW1--></div>" +
				  "<div id='SW2'><!--SW2--></div>" +
				  "<div id='SW3' class='last'><!--SW3--></div>" +
				  "</div>"
			}

	-	`templatePrefix`

		undefined by default

		What to insert before a template.  In bardtest, this is defined as:

			"<html><head>" +
			"<meta http-equiv='Content-Type' content='text/html;charset=ISO-8859-1'>" +
			"<base href='" + gBaseUrl + "' />" +
			"<base target='_blank' />" +
			"<link type='text/css' rel='stylesheet' href='bardtest.css'>" +
			"</head><body>"

	-	`templatePostfix`

		undefined by default

		What to insert after a template.  In bardtest, this is defined as:

			"</body></html>"

	-	`otherParams`

	  	undefined by default
	
		In barddemo, these are set to the following (for now you will have to look at the source code to comprehend their meaning)

			{
				"t_e" : 1,
				".intl" : "us"
			}

	-	`events`
	
	  	undefined by default

		This object defines what kinds of events your app might pass to darla via the event function.  Each property (e.g. the name of the event) maps an event "matrix" providing information about what the event should do.  The matrix is itself an object, and has the following properties:
		
		-	`sp`
		
		 	The space ID associated with this event
		
		-	`ps`
		
			The positions called out for this event
			
		-	`bg`
		
			The background color of the iframe that contains this event; only applies to the simple template
			
		-	`ca`
		
			The cancellability for this event; currently `true` or `false` (null), maybe could migrate to the actual timeout value instead (with the default record providing the default value, possible 0); if another event comes in before this time, the associated update is cancelled. NOTE: currently all events are cancellable.  this flag just invokes a longer delay.
		
		-	`lv`

			The "level" of this event, which generally indicates whether we take UI action (place/update an ad) or just register the space id.  The semantics of the values are as follows:
			
			*	-1
			
				no ads refreshed, no client-side counting invoked, but do count an event as transpiring. if auto-rotation is on, this will periodically update ads without generating any no-ad space ID beacons (this may move to the default action when auto-rotation is on) additionally, it allows calls to the event function to be sprinkled throughout the	code, while controlling their impact in your config object.  if a space ID has this	event level in its event record, then an event-time override of the level will be ignored.

			*	0
			 
				no ad update, but do invoke client-side spaceID counting

			*	1
			
			 	update ads if the ad timer has expired; if no ad is updated, due to not enough time expired, invoke the spaceID.  most ad-bearing actions that involve direct user action like a mouse click will have this event level.

			*	2
			
			 	really really update ads, regardless of the timer status; for forcing ads in certain situations, for example when a previously hidden ad iframe is shown
			
		proposed additional properties:
		
		of: - a way to cancel the intl offset or provide a spaceID-specific intl offset
		op: - other params for the script URL, for this action; should these mask otherParams?

		example: 
	
		here is what the events value looks like in bardtest

			{
				"default" :	{ lv:1, sp:"150550001", bg:"E4E5DB", ca:false, ps:"SKY,W1,MNW,SW1,SW2,SW3" },
				"general" : { lv:1, sp:"150550280" }, // 150550001
				"welcomeFirst" : { lv:-1, sp:"150550280" },
				"openCompose" :	{ lv:2, sp:"150550573", bg:"F4F5EB" },
				"idle" : { lv:-1, sp:"150550742" },
				"scrollInbox" :	{ lv:1, sp:"150550837", ca:true },
				"scrollView" : { lv:1, sp:"95604111", ca:true, ps:"FB2" }
			}


-	`event(action, overrides)`

	Register a page view and possibly update ads.  This is the main call for triggering an ad fetch.

	`action` is the human-readable string representing a space ID, not the numeric space ID itself. These strings are expected to appear as keys in the configuration event matrix.

	`overrides` object containing parameters for overriding the standard parameters associated with the action ID.  These values override the ones stored in the event matrix, so the caller can modify single callouts to this action ID.  The event's level is not overridden if it's set to -1 (no-op).

@doc */

if (typeof YAHOO === "undefined") var YAHOO = {};
if (typeof YAHOO.ads === "undefined") YAHOO.ads = {};
YAHOO.ads.darla = {

	// ---------- Begin library data - should all be treated as private ----------

	_isSafari: navigator.userAgent.match(/AppleWebKit\/([^ ]*)/),
	// TODO: module format will allow us to avoid repeating the WebKit check here:
	_isIE: ( !navigator.userAgent.match(/AppleWebKit\/([^ ]*)/) && !navigator.userAgent.match(/opera/gi) && navigator.userAgent.match(/msie/gi) ),

	_beacons: [ ],

	_eventTimer : null,
	_lastEvent : null,

	_handoffStore: null,
	_renderStore: null,

	_rotationTimer : null,
	_rotationTime : (new (Date)()).getTime(),
	_rotationEvents : false,

	_config : null,
	
	_baseConfig : {

		callFrame: "fccall", 

		callScript: "fc.php",

		domainScript: "fc.php", //server side script which emits a short document to set document.domain. clients use this on IE to allow cross-frame access, which is disallowed for dynamic iframe documents once the parent page sets

		rotation: 5000, // TODO: should this default to a larger value? should be whatever is deemed to be the "standard" value -- kevykev 2007.04.26

		autoRotation: false,

		autoRotationWindow: 1000, // the period before rotation timer expiration within which we must see user activity to trigger an ad at the next timer expiration.  we suggest keeping this number small to increase the chance the user sees the ad (the logic being they just did something and are therefore engaged

		cancelShortEvents: true, // xxx: (iain 22-Aug-06) this property should be removed as a config option, we want it always set to true, but here is the old documentation: If you're using any sort of mechanism that might generate a whole lot of events, like responding to mousemove or scroll events, this should be true to allow short-lived events to be ignored.  please discuss your decision with the ad group if you wish to set this to false.

		doubleBuffering: true,  // whether to support offscreen rendering of ads in alternating containers. STRONGLY RECOMMENDED FOR IFRAME RENDERING OF INTL ADS ON IE.  Ignored on Safari at the moment, due to Safari's treatment of IFRAMES with display:none (contentWindow not available)

		fullDoubleBuffering: true, // whether to support full offscreen rendering of ads and switching each one individually using load hanlders

		autoSwitchRendering: true,// when this is true, we will switch between target elements as needed, to reduce a cross-frame scripting problem on IE. by definition we look for an alternate, non-iframe element (typically a DIV) whose ID is the give ID plus the string "alt".

		property: "yahoo",
		
		encoding: "utf-8",
		
		standardDelay: 100, // the standard time in milliseconds to wait before an actionable user event leads to an ad rotation event. this number exists because we assumed we are often doing heavy computation in response to a user event, such as firing off an XHR request ... but it is now unclear this is really needed
		
		// xxx: (iain 25-Aug-06) consider removing this or making it and cancellableDelay one number
		
		cancellableDelay: 500, // we provide a mechanism that allows a barrage of similar events to resolve to a single ad lookup (example: updating ads in response to scrolling, which generates lots of JS events); actions can be marked as "cancellable", and another action that comes through fast enough (within the amount of milliseconds specified by this value) will cause the previous one to be cancelled.

		beaconDelay: 2000,// xxx (iain 25-Aug-06) consider deprecating this, it was added for candygram perf. default amount of time (milliseconds) to wait to send a beacon after an event has triggered a rotation

		beaconUrl: "http://geo.yahoo.com/serv?s=", // URL to be used for an image beacon
		
		throbberDelay: 350, // milliseconds to wait before writing about:blank to anti-throbber iframe (after fetching ad content into an iframe) to stop throbber from going round on FF

		simpleTemplate:
			"<html><head><!--ENCODING--><base target='_blank' /><!--STYLE--></head><body style='overflow:hidden;'>" +
			"<table width='100%' height='100%'><tr><td align=center valign=top><!--ADHTML--></td></tr></table>" +
			"</body></html>", 

		simpleTemplateEncodingTag:
		"<meta http-equiv='Content-Type' content='text/html;charset=__ENCODING__'>",// the meta tag defining the charset encoding of data in the ad system

		simpleTemplateStyleTag:
		"<style> body { background-color: __BGCOLOR__; } </style>"  

 },

	// there are some configuration values that aren't part of the default config object.  document them here

	setConfig : function ( config, initialState ) {

		// See the Darla documentation for details on the configuration object
		YAHOO.ads.darla._config = config;

		if ( initialState === 0 )
			YAHOO.ads.darla._config._startRotationTimer ();

	},

	event : function ( action, overrides ) {
		if ( YAHOO.ads.darla._config == null ) return;

		YAHOO.ads.darla.log ( "YAHOO.ads.darla.event called with action: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + "-" + YAHOO.ads.darla.lookupSpaceID (  _proxy_jslib_handle(null, 'action', action, 0, 0) ), true );

		var settings = YAHOO.ads.darla.lookupActionSettings (  _proxy_jslib_handle(null, 'action', action, 0, 0), overrides );


		if (( settings.lv == -1 ) && !YAHOO.ads.darla.getConfigSetting ( "autoRotation" ))
			// Ads and beacons disabled for this action, an no auto-rotation to update
			return;


		// We provide a mechanism that allows a barrage of similar events to
		// resolve to a single ad lookup (example: updating ads in response
		// to scrolling, which generates lots of JS events); actions can be
		// marked as "cancellable", and another action that comes through fast
		// enough will cause the previous one to be cancelled:

		// TODO: this might be moot code.  _startEventTimer currently always clears
		// any outstanding timer before starting a new one.
		if ( YAHOO.ads.darla._eventTimer != null ) {
			if (( YAHOO.ads.darla.getConfigSetting ( "cancelShortEvents" ) == true ) ||
					( YAHOO.ads.darla._lastEvent && YAHOO.ads.darla._lastEvent.settings && YAHOO.ads.darla._lastEvent.settings.ca )) {
				clearTimeout ( YAHOO.ads.darla._eventTimer );
				YAHOO.ads.darla._eventTimer = null;

				YAHOO.ads.darla.log ( "YAHOO.ads.darla.event: cancelling prior short-lived event", true );
			}
		}


		YAHOO.ads.darla.log ( "YAHOO.ads.darla.event firing timer for action: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + "-" + settings.sp, true );

		// TODO: maybe ALL actions should be cancellable?  or have two levels of cancellability,
		// one really short and one not so short?


		YAHOO.ads.darla._lastEvent = { action:  _proxy_jslib_handle(null, 'action', action, 0, 0), settings: settings };
		YAHOO.ads.darla._startEventTimer ( YAHOO.ads.darla._lastEvent );

		// TODO: see comments about re-entrancy in _processEvent
	},


	// Send a beacon for the given action, possibly after a delay.
	 
	// action: The human-readable string representing a space ID, not the numeric space ID itself. TODO: allow passing Number (check typeof). These strings are expected to appear as keys in the configuration event matrix.
	// delay: number of milliseconds to postpone the beacon (using a timeout)

	sendBeacon : function ( action, delay ) {
	
		if ( delay === true ) // so callers can just say true
			delay = YAHOO.ads.darla.getConfigSetting ( "beaconDelay" );
		
		if ( typeof delay == "number" && delay > 0 ) {
		     _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)( "YAHOO.ads.darla.sendBeacon( '" +  _proxy_jslib_handle(null, 'action', action, 0, 0) + "', null )", delay );
			return;
		}

		var spaceid = YAHOO.ads.darla.lookupSpaceID (  _proxy_jslib_handle(null, 'action', action, 0, 0) );
		if (( spaceid == null ) || ( spaceid == "undefined" ) || ( spaceid == "null" ))
			return;

		var url = YAHOO.ads.darla._getBeaconUrl ( spaceid );
		if ( url == null || url == "" ) {
			// This is not necessarily an error-- properties might
			// throttle beaconing for performance reasons.
			YAHOO.ads.darla.log ( "ignoring spaceid (no beacon url provided): " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + "-" + spaceid, true );
			return;
		}


		// Report the space id by creating a throw-away Image element,
		// and setting its url to the beacon server. We attach onload 
		// and onerror handlers to keep the element from being garbage- 
		// collected until after the object has loaded.  These in turn
		// must be cleared for the Image to be collected.
		//
		// TODO: out of paranoia, I collect this in an array and explicitly
		// clear them when loaded.  Is this really necessary?  One benefit
		// to using an array, which has not been implemented, would be to 
		// space out quickly-reported beacons so they don't pile up one
		// after the other (e.g. arrowing down through a list of items
		// where each selection results in a space ID).  Or, once one fires,
		// immediately fire the next waiting one, rather than having a
		// chain of timeouts, one for each beacon.

		
		if ( YAHOO.ads.darla._beacons == null )
			YAHOO.ads.darla._beacons = [ ];

		// using an Image instead of an element avoids the permanent
		// "Loading" status message on IE.  For Mozilla, we need the
		// "throbber hack" of reloading an empty iframe.
		var id = new (Date)().getTime();
		while (  _proxy_jslib_handle(YAHOO.ads.darla._beacons, ("x"+id), 0, 0) != null )
			(id= _proxy_jslib_assign_rval('--', 'id', '', '', id));

		id = "x" + id;
		var beacon = new (Image)();
		 _proxy_jslib_assign('', YAHOO.ads.darla._beacons, (id), '=', ( beacon));

		beacon.onload = function() { eval(_proxy_jslib_proxify_js(( "'onload'; YAHOO.ads.darla._beacons['" +id+ "']=null;this.onload = null; this.onerror = null; YAHOO.ads.darla._throbberHack( true );" ), 0, 0) ) };
		beacon.onerror = function() { eval(_proxy_jslib_proxify_js(( "'onerror'; YAHOO.ads.darla._beacons['" + id + "']=null;this.onload = null; this.onerror = null; YAHOO.ads.darla._throbberHack( true );" ), 0, 0) ) };

		 _proxy_jslib_assign('', beacon, 'src', '=', ( url));


		YAHOO.ads.darla.log ( "beaconing spaceid: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + " - " + spaceid );

	},


	// Causes the current outstanding ad operation to stall for a short time.  Provided as a way for GUIs to postpone ad fetching during highly-interactive operations, such as drag-and-drop.
	// delayAmount: Number of milliseconds to postpone any outstanding updates.  Defaults to the "cancellableDelay" value in the current configuration.
	stallAdRequest : function ( delayAmount ) {
		if (( YAHOO.ads.darla._config == null ) || ( YAHOO.ads.darla._lastEvent == null ))
			return;

		if ( delayAmount == null )
			delayAmount = YAHOO.ads.darla.getConfigSetting ( "cancellableDelay" );
	
		if ( delayAmount == null )
			return;

		// TODO: Not very reentrant-friendly.  Oh well.
		YAHOO.ads.darla._startEventTimer ( YAHOO.ads.darla._lastEvent, delayAmount );

		YAHOO.ads.darla.log ( "Stalling outstanding ad event", true );
	},


	// Lookup a space ID (e.g., 150550280) based on an action ID (e.g., "mail_welcome")
	// action: A string identifier giving an action ID, for looking up in the configuration event matrix
	// getRawID: boolean value, set to true to return the raw entered ID, with no internationalization offset applies (default: false or null)
	
	// returns a number, the resolved space ID, possibly with int'l offset applied
	lookupSpaceID : function ( action, getRawID ) {
		if ( YAHOO.ads.darla._config == null ) return null;

		var rec =  _proxy_jslib_handle(YAHOO.ads.darla._config.events , ( _proxy_jslib_handle(null, 'action', action, 0, 0)), 0, 0);
		if ( rec == null ) return null;

		var sid = rec.sp;
		if ( getRawID ) return sid;

		if ( sid == null ) return null;

		if ( YAHOO.ads.darla._config.spaceIdOffset == null )
			YAHOO.ads.darla._config.spaceIdOffset = 0;

		return (( sid - 0 ) + ( YAHOO.ads.darla._config.spaceIdOffset - 0)); // string->number conversion
	},


	// Lookup all settings (including computed space ID) based on an action ID (e.g., "mail_welcome")
	// action: A string identifier giving an action ID, for looking up in the configuration event matrix
	// overrides: object settings that should override the action settings or default settings in the current configuration
	
	// returns an object containing the resolved settings (merged overrides, action settings, and default settings) for the given action ID
	lookupActionSettings : function ( action, overrides ) {
		if ( YAHOO.ads.darla._config == null ) return overrides;

		var results = { };

		// apply the defaults, if present

		var rec =  _proxy_jslib_handle(YAHOO.ads.darla._config.events , ( "default" ), 0, 0);
		if ( rec != null ) {
			for ( var f in rec )
				 _proxy_jslib_assign('', results, (f), '=', (  _proxy_jslib_handle(rec, (f), 0, 0)));
		}

		// apply the normal settings for the action
		var rec =  _proxy_jslib_handle(YAHOO.ads.darla._config.events , ( _proxy_jslib_handle(null, 'action', action, 0, 0)), 0, 0);
		if ( rec != null ) {
			for ( var f in rec )
				 _proxy_jslib_assign('', results, (f), '=', (  _proxy_jslib_handle(rec, (f), 0, 0)));
		}

		// apply the overrides for this particular call
		if ( overrides != null )
			for ( var f in overrides )
				 _proxy_jslib_assign('', results, (f), '=', (  _proxy_jslib_handle(overrides, (f), 0, 0)));


		// in particular, get the computed space ID --
		results.sp = YAHOO.ads.darla.lookupSpaceID (  _proxy_jslib_handle(null, 'action', action, 0, 0) );

		// -- account for the global level override --
		if ( YAHOO.ads.darla._config.levelOverride != null )
			results.lv = YAHOO.ads.darla._config.levelOverride;

		// -- but don't override an original event level of -1 --
		if (  _proxy_jslib_handle(YAHOO.ads.darla._config.events , ( _proxy_jslib_handle(null, 'action', action, 0, 0)), 0, 0) == -1 )
			result.lv = -1;

		// -- and compute the paramaterized locations:
		// (convert a position list like SKY,MNW,W1 to a list with
		//  disposition parameters, such as SKY:SKY,MNW:HandoffFunction,W1:W1)
		var ps = results.ps;
		if ( ps != null ) {
			var psStr = "";
			var psa = ps.split ( "," );

			for ( var i=0; i<psa.length; (i= _proxy_jslib_assign_rval('++', 'i', '', '', i)) ) {
				if ( psStr.length > 0 ) psStr += ",";

				var pos =  _proxy_jslib_handle(psa, (i), 0, 0);

				var d =  _proxy_jslib_handle(YAHOO.ads.darla._config.destinationMap, (pos), 0, 0);
				if ( d != null && d != "" ) {
					switch ( typeof d ) {

					// the destination is either an element (by ID) or a function
					case "string":
						psStr += pos;
						var e =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( d );
						if ( e != null ) {
							psStr += ":";
							if ( e.tagName.toLowerCase() == "iframe" )
								psStr += "!"; // bang alone means call the main callback
							else
								psStr += d;
						} else if ( typeof d == "function" )
							psStr += ":" + d;
						break;

					// the only thing we currently support here is an array of element IDs
					case "object":
						if ( d.length ) {
							// due to time constraints, we only support processing
							// these here in the JS, through the handoff callback.
							// it might be a nice option to let the PHP handle it
							// as well, with syntax along the lines of:
							//   ADID:LOC1+LOC2+LOC3

							psStr += "n" + d.length + pos + ":!";
								 // bang alone means call the main callback
						}
						break;
					}

				} else
					// just render it in the calling frame
					psStr += pos;

			}

			results.psStr = psStr;
		}


		if ( YAHOO.ads.darla._config.verboseLogging ) {
			var s = "";
			for ( var f in results )
				s += f + ":" +  _proxy_jslib_handle(results, (f), 0, 0) + "; ";
			YAHOO.ads.darla.log ( "computed action settings: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + " - " + s, true );
		}

		return results;
	},


	// Retrieve a configuration setting, performing lookups in both the costum and base configuration objects
	// key: string indicating the configuration setting to look up
	// customOnly: boolean value indicating whether to inspect only the installed configuration (e.g. do not lookup settings in the base configuration)

	// returns the value for the requested configuration setting.
	getConfigSetting : function ( key, customOnly ) {
		var value = null;
		if ( YAHOO.ads.darla._config )
			 value= _proxy_jslib_assign_rval('', 'value', '=', (  _proxy_jslib_handle(YAHOO.ads.darla._config, (key), 0, 0)), value);
		
		if ( customOnly || (  _proxy_jslib_handle(null, 'value', value, 0, 0) === null ))
			// allow null to really be null-- to use a default, leave a key undefined
			return  _proxy_jslib_handle(null, 'value', value, 0, 0);

		if (  _proxy_jslib_handle(null, 'value', value, 0, 0) == null )
			return  _proxy_jslib_handle(YAHOO.ads.darla._baseConfig, (key), 0, 0);

		return  _proxy_jslib_handle(null, 'value', value, 0, 0);
	},


	// Retrieve an HTML template for a specified ad-containing element
	// dest: string id of the element (generally an IFRAME) to look up.
	
	// returns a string containing an HTML template constructed based on the current configuration object
	getTemplate : function ( dest ) {
		var c = YAHOO.ads.darla._config;
		if ( c == null || c.templates == null ||  _proxy_jslib_handle(c.templates, (dest), 0, 0) == null )
			return null;

		var e =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( dest );
		if ( e == null || e.tagName.toLowerCase() != "iframe" )
			return null;

		var t = [];
		if ( c.templatePrefix !== null ) {
			 _proxy_jslib_assign('', t, (t.length), '=', ( c.templatePrefix));
			if ( YAHOO.ads.darla._isIE )
				 _proxy_jslib_assign('', t, (t.length-1), '=', (  _proxy_jslib_handle( _proxy_jslib_handle(t, (t.length-1), 0, 0), 'replace', '', 1, 0) ( new (RegExp) ( "<base href=.*?>", "i" ), "" )));
		}
		 _proxy_jslib_assign('', t, (t.length), '=', (  _proxy_jslib_handle(c.templates, (dest), 0, 0)));
		if ( c.templatePostfix !== null )
			 _proxy_jslib_assign('', t, (t.length), '=', ( c.templatePostfix));

		return t.join("");
	},


	// retrieve the "simple" HTML template for ads and insert the given ad HTML into it.
	// adHtml: string representing the ad HTML to be inserted into the template.

	// returns an HTML string template with the encoding set and ad HTML inserted, ready for rendering
	fillSimpleTemplate : function ( pos, adHtml ) {
	
		var t = YAHOO.ads.darla.getConfigSetting ( "simpleTemplate" );
		if (( t == null ) || ( t == "" ))
			return null;

		var e = YAHOO.ads.darla.getConfigSetting ( "encoding" );
		if (( e != null ) && ( e != "" )) {
			var et = YAHOO.ads.darla.getConfigSetting ( "simpleTemplateEncodingTag" );
			if ( et ) {
				et =  _proxy_jslib_handle(et, 'replace', '', 1, 0) (new (RegExp) ( "__ENCODING__", "g" ), e );
				t =  _proxy_jslib_handle(t, 'replace', '', 1, 0) (new (RegExp) ( "<!-"+"-ENCODING-"+"->", "g" ), et );
			}
		}

		var e = YAHOO.ads.darla.getConfigSetting ( "bg" );
		if (( e != null ) && ( e != "" )) {
			var et = YAHOO.ads.darla.getConfigSetting ( "simpleTemplateStyleTag" );
			if ( et ) {
				et =  _proxy_jslib_handle(et, 'replace', '', 1, 0) (new (RegExp) ( "__BGCOLOR__", "g" ), e );
				t =  _proxy_jslib_handle(t, 'replace', '', 1, 0) (new (RegExp) ( "<!-"+"-STYLE-"+"->", "g" ), et );
			}
		}

		// replace $ with encoded value %24 to make replace( new RegExp() ) work better
		adHtml =  _proxy_jslib_handle(adHtml, 'replace', '', 1, 0)(/\$/g,"%24");

		t =  _proxy_jslib_handle(t, 'replace', '', 1, 0) (new (RegExp) ( "<!-"+"-ADHTML-"+"->", "g" ), adHtml );

		YAHOO.ads.darla.log ( "built from simple template: " + t, true );
		
		return t;
	},


	// pass a message through to the logging callback specified in the current configuration
	// message: string value of the message to be logged
	// verboseOnly: boolean value, if true, send this message through only if verbose logging is turned on

	log : function ( message, verboseOnly ) {
		if ( YAHOO.ads.darla._config == null || YAHOO.ads.darla._config.log == null ) return;
		if ( verboseOnly && YAHOO.ads.darla._config.verboseLogging != true ) return;

		if ( message == null ) message = "null";

		var e;
		try {
			YAHOO.ads.darla._config.log ( message );
		} catch ( e ) { };
	},


	// Utility for stripping ad HTML that has already been rendered once, in order to allow it to be safely rendered a second time. Generally used when transferring innerHTML from one ad container to another, so that, e.g., CSC beacons do not fire twice.
	// adHtml: string, the HTML fragment to be stripped

	// returns string containing adHtml with all SCRIPT tags and CSC beacons removed
// TODO: I claim dead code.  Commenting out for now, should be stripped after an engineering review -- kevykev
//	stripAdHtml : function ( adHtml ) {
//
//		// Note use of "[^<>]*?" instead of ".*?" at various points to
//		// keep the scope of these REs correct, esp. the <img> one
//		
//		// Multi-line REs will not consistently cross all these characters on Mozilla
//		// (I haven't bothered to track down which.)
//		adHtml = adHtml.replace( /[\t\n\r\f\v]/g, " "); 
//
//		adHtml = adHtml.replace ( new RegExp ( '<scr'+'ipt[^>]*?>.*?<\/scr'+'ipt>', "igm" ), "" );
//		adHtml = adHtml.replace ( new RegExp ( '<!--[^>]*?-->', "igm" ), "" );
//		adHtml = adHtml.replace ( new RegExp ( '<img ([^>]*?class[^>]*?yzq[^>]*?>)', "igm" ), "" );
//		adHtml = adHtml.replace ( new RegExp ( '^[ ]*', "igm" ), "" );
//
//		if ( YAHOO.ads.darla._config && YAHOO.ads.darla._config.log && YAHOO.ads.darla._config.verboseLogging  ) {
//			var detail = "";
//			for ( var i=0; i<adHtml.length && i<100; ++i )
//				detail += " " + adHtml.charCodeAt (i);
//			YAHOO.ads.darla.log ( "stripped ad html::>" + adHtml + "<::>" + detail, true );
//		}
//		
//		return adHtml;
//	},



	// ---------- Begin internal functions ----------
	// xxx: (iain 08-Sep-06) many of the above are really internal functions too ... i suggest we make private functions really private by just referencing them from closures
	
	/**
	 * Start the event timer, which is a short timeout made at the time an event is registered.  This allows rapid-fire sequences of events to coalesce into an single space ID action.
	 *
	 * @param {Object} eventObject The object describing this action, like the YAHOO.ads.darla._lastEvent object.  Contains the action ID and compiled action settings.
	 * @param {Number} delayAmount Time in milliseconds to wait before the action is actually processed.
	 */
	_startEventTimer : function ( eventObject, delayAmount ) {

		if ( YAHOO.ads.darla._eventTimer != null ) {
			clearTimeout ();
			YAHOO.ads.darla._eventTimer = null;

			// TODO: we always clear out pending events here.
			// Should we be preserving the action, and beaconing it?
		}

		if ( eventObject == null ) return;

		var delay = ( delayAmount != null ) ? delayAmount :
					// if an action is cancellable, wait a bit longer before reporting it
					( eventObject.settings.ca ? 
						 	YAHOO.ads.darla.getConfigSetting ( "cancellableDelay" ) :
						 	YAHOO.ads.darla.getConfigSetting ( "standardDelay" ) );

		YAHOO.ads.darla._lastEvent = eventObject;
		YAHOO.ads.darla._eventTimer =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)( "YAHOO.ads.darla._processEvent('" +  _proxy_jslib_handle(eventObject, 'action', '', 0, 0) + "')", delay );

	},

	
	/**
	 * Actually process an event, resulting generally in either an ad fetch or a spaceID beacon
	 *
	 * @param {String} action The human-readable string representing a space ID, not the numeric space ID itself. TODO: allow passing Number (check typeof).
	 * These strings are expected to appear as keys in the configuration event matrix.
	 */
	_processEvent : function ( action ) {

		YAHOO.ads.darla.log ( "YAHOO.ads.darla._processEvent firing for action: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) );

		YAHOO.ads.darla._eventTimer = null;

		if ( YAHOO.ads.darla._config == null ) return;

		if ( YAHOO.ads.darla._lastEvent == null ||  _proxy_jslib_handle(YAHOO.ads.darla._lastEvent, 'action', '', 0, 0) !=  _proxy_jslib_handle(null, 'action', action, 0, 0) ) {
			// TODO: lame re-entrancy support, here, starting with the fact
			// that we store only one timer (_eventTimer) and clear it here.
			// Then there's the settings object, which is also a singular property.
			// Use a closure to send the settings object across the timeout, instead?
			return null;
		}


		YAHOO.ads.darla._recordEvent();

		var settings = YAHOO.ads.darla._lastEvent.settings;	
		var level = settings.lv;
		if ( level == null )
			level = ( settings.sp != null ) ? 1 : -1;

		if ( level < 0 ) {
			if ( YAHOO.ads.darla.getConfigSetting ( "autoRotation" ))
				// transform into an action that can trigger ad rotation,
				// if the timer state allows it
				level = 1;

			else
				return; // do nothing - no ads, no beacon
		}

		// Some action IDs are so "strong" that they ignore the timer;
		// reset the state and update ads now:
		if ( level > 1 ) {
			YAHOO.ads.darla._clearRotationTimer ();
			level = 1;
		}


		// ad level 1 - if the ad rotation time has passed, time to show ads.
		// ad level 2 - we've forced the rotation state, above, to show ads
		// else, send a beacon

		if (( level == 1 ) && YAHOO.ads.darla._checkRotation ( settings.ro ) ) {

			// finally: fetch the ads!
			
			if ( YAHOO.ads.darla._call (  _proxy_jslib_handle(null, 'action', action, 0, 0), settings ) == true )
				return;


			// we do not reset the activity state to zero until we actually
			// get the first callback from the ad script -- if there's an
			// error, we want to try again as soon as possible, and the
			// activityState needs to remain at 1 for that to happen
		}


		// No ad fetch took place - send a beacon instead.
		//
		// As a general rule, we can't beacon page views for which we are
		// fetching ads.  Server log trolling picks up ad calls.  So, we
		// report space IDs only when the ad fetch function above says it
		// didn't do anything (YAHOO.ads.darla._call returned false)
		//
		// TODO: migration to CSC-based pageviews will likely render this obsolete.
		// Will developers still want this capability?

		if ( YAHOO.ads.darla.getConfigSetting ( "beaconsDisabled" ) != true )
			YAHOO.ads.darla.sendBeacon(  _proxy_jslib_handle(null, 'action', action, 0, 0), YAHOO.ads.darla.getConfigSetting ( "beaconDelay" ) );

	},


	/**
	 * If auto-rotation is on, note that we've seen an event --
	 * but only within the autoRotationWindow, which may be smaller
	 * than the rotation period itself.
	 */
	_recordEvent : function () {

		if ( YAHOO.ads.darla.getConfigSetting ( "autoRotation" )) {
			var wndw = YAHOO.ads.darla.getConfigSetting ( "autoRotationWindow" );
			var rotation = YAHOO.ads.darla.getConfigSetting ( "rotation" );
			if ( wndw == null || wndw > rotation )
				wndw = rotation;
			
			// Only record seeing events after some delay.  This allows longer
			// rotation periods that only rotate at some smaller minimum time
			// since the last user action.  For example, having a regular rotation
			// of 30 seconds, but only updating when there's been user activity
			// within the last 5 seconds.
			// Additionally, if the rotationTime is 0, the ads were recently cleared
			// and we want to allow the next request or timer to update the ads
			if ( ( YAHOO.ads.darla._rotationTime == 0 ) ||
					( (new (Date)()).getTime() - YAHOO.ads.darla._rotationTime ) > ( rotation - wndw ))
				YAHOO.ads.darla._rotationEvents = true;
		}
	},


	/**
	 * Call the ad script on the server.
	 *
	 * @param {String} action The human-readable string representing a space ID, not the numeric space ID itself. TODO: allow passing Number (check typeof).
	 * These strings are expected to appear as keys in the configuration event matrix.
	 * @param {Object} settings The call settings for this ad update.
	 * @return {Boolean} True if the script was called, false if there was an error.
	 */
	_call : function ( action, settings ) {

		if ( YAHOO.ads.darla._config == null ) return;
		var config = YAHOO.ads.darla._config;


		// Check a bunch of conditions, and bail if there are problems.
		
		if ( config.callFrame == null ) {
			YAHOO.ads.darla.log ( "YAHOO.ads.darla._call called, but no call iframe specified.", true );
			return;
		}

                var adFrame;
		if (settings.callFrame == null) {
			adFrame =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( YAHOO.ads.darla.getConfigSetting ( "callFrame" ));
		} else {
			adFrame= _proxy_jslib_handle(document, 'getElementById', '', 1, 0)(settings.callFrame);
		}
		YAHOO.ads.darla.log("callFrame specified: "+adFrame.id, true);

		if ( adFrame == null ) {
			YAHOO.ads.darla.log ( "YAHOO.ads.darla._call called, but call iframe not found, id: " + config.callFrame, true );
			return;
		}

		var spaceid = settings.sp;
		if ( spaceid == null || spaceid == "" ) {
			YAHOO.ads.darla.log ( "YAHOO.ads.darla._call called, but null space ID found; the action was: " +  _proxy_jslib_handle(null, 'action', action, 0, 0), true );
			return false;
		}


		var loc = settings.psStr;
		if ( loc == "" ) {
			YAHOO.ads.darla._clearRotationTimer ();
			YAHOO.ads.darla.log ( "YAHOO.ads.darla._call called, but no positions to update; the action was: " +  _proxy_jslib_handle(null, 'action', action, 0, 0), true );
			return false;
		}


		// Build the url parameters

		var extraMime = settings.em;
		if ( extraMime == null )
			extraMime = config.extraMime;

		var bgColor = settings.bg;
		if ( bgColor == null ) bgColor = "";

		// clear any pending handoffs
		YAHOO.ads.darla._handoffStore = null;

		// TODO: allow passing YAHOO.ads.darla._loaded (needs an eval operation in the PHP)
		var url = [ YAHOO.ads.darla.getConfigSetting ( "callScript" ) + "?cb=YAHOO.ads.darla._loaded" ];

		 _proxy_jslib_assign('', url, (url.length), '=', ( "p=" + YAHOO.ads.darla.getConfigSetting ( "property" )));
		 _proxy_jslib_assign('', url, (url.length), '=', ( "f=" + spaceid));
		 _proxy_jslib_assign('', url, (url.length), '=', ( "l=" + loc));
		 _proxy_jslib_assign('', url, (url.length), '=', ( "en=" + YAHOO.ads.darla.getConfigSetting ( "encoding" )));
		 _proxy_jslib_assign('', url, (url.length), '=', ( "rn=" + (new (Date)().getTime())));

		if ( extraMime != null )
			 _proxy_jslib_assign('', url, (url.length), '=', ( "em=" + extraMime));

		if ( config.target )
			 _proxy_jslib_assign('', url, (url.length), '=', ( "tgt=" + config.target));

		if (  _proxy_jslib_handle(config, 'domain', '', 0, 0) )
			 _proxy_jslib_assign('', url, (url.length), '=', ( "dm=" +  _proxy_jslib_handle(config, 'domain', '', 0, 0)));

		if ( settings.op ) {
			var params = settings.op;
			for ( var f in params )
				 _proxy_jslib_assign('', url, (url.length), '=', ( f + "=" +  _proxy_jslib_handle(params, (f), 0, 0)));
		}

		if ( config.otherParams ) {
			var params = config.otherParams;
			for ( var f in params ) {
				if ( settings.op &&  _proxy_jslib_handle(settings.op, (f), 0, 0) )
					continue;

				 _proxy_jslib_assign('', url, (url.length), '=', ( f + "=" +  _proxy_jslib_handle(params, (f), 0, 0)));
			}
		}

		url = url.join ( "&" );


		YAHOO.ads.darla.log ( "ad request: " +  _proxy_jslib_handle(null, 'action', action, 0, 0) + "; url=" + url );

		// Finally... get some ads!
		 _proxy_jslib_handle( _proxy_jslib_handle(adFrame.contentWindow, 'location', '', 0, 0), 'replace', '', 1, 0) ( url );

		return true;
	},


	/**
	 * Mark the current time as the start time for a new ad rotation period.
	 * This is generally only called right after loading ads.
	 *
	 * @param {Number} delayAmount The amount of time a new ad should persist before events cause an update.
	 */
	_startRotationTimer : function ( delayAmount ) {
		if ( YAHOO.ads.darla._config == null ) return;
	
		YAHOO.ads.darla._clearRotationTimer ();

		// clear the "we've seen events" flag.  in the auto-rotate
		// case, we will update ads at the expiration of the rotation
		// timer if any events have come through in the interim.
		YAHOO.ads.darla._rotationEvents = false;
		YAHOO.ads.darla._rotationTime = (new (Date)()).getTime();

		// if auto-rotation is on, start the timer
		if ( YAHOO.ads.darla.getConfigSetting ( "autoRotation" ) ) {
			if ( delayAmount == null )
				delayAmount = YAHOO.ads.darla.getConfigSetting ( "rotation" );
			if ( delayAmount == null )
				return;

			YAHOO.ads.darla._rotationTimer =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0) ( "YAHOO.ads.darla._rotateAdState()", delayAmount );
			YAHOO.ads.darla.log ( "start ad timer: " + delayAmount, true );
		}
	},

	
	/**
	 * Clear the ad rotation start time, so that the
	 * next time we check, the period is considered expired.
	 *
	 */
	_clearRotationTimer : function () {
		YAHOO.ads.darla._rotationTime = 0;

		if ( YAHOO.ads.darla._rotationTimer != null ) {
			clearTimeout ( YAHOO.ads.darla._rotationTimer );
			YAHOO.ads.darla._rotationTimer = null;
		}
	},


	/**
	 * Response handler for the auto-rotation timer.  Fires an
	 * ad fetch immediately if auto-rotation is still turned on,
	 * otherwise places the library into a state where the next
	 * ad-bearing event will trigger a new ad fetch.  
	 */
	_rotateAdState : function () {

		YAHOO.ads.darla._clearRotationTimer ();

		if ( YAHOO.ads.darla.getConfigSetting ( "autoRotation" ) && YAHOO.ads.darla._rotationEvents ) {
			YAHOO.ads.darla.event ( "default" );
		}

		YAHOO.ads.darla._rotationEvents = false;
	},


	/**
	 * See if the current ad has been displayed for at least the given period.
	 *
	 * @param {Number} rotationTime The amount of time that the last ad should persist (after which events can cause an update).  If null, the global default is used.
	 * @return {Boolean} True if the current as has been visible for rotationTime milliseconds.
	 */
	_checkRotation : function ( rotationTime ) {
		if ( YAHOO.ads.darla._config == null ) return false;

		if ( YAHOO.ads.darla._rotationTime == 0 ) return true;

		if ( rotationTime == null )
			rotationTime = YAHOO.ads.darla.getConfigSetting ( "rotation" );

		return ( YAHOO.ads.darla._rotationTime + rotationTime <= ( new (Date)().getTime() ) );
	},


	/**
	 * Call the "throbber hack", with a built-in self-restarting delay so we can call it repeatedly in short succession but only have it take the last time.
	 */
	_throbberHack : function ( delay ) {
		// TODO: document more thoroughly what this does for clients,
		// and provide a drop-in implementation (possibly even entirely
		// internalized to this library).
		// In mail beta, we modified this so that it is always on a delay,
		// and so that multiple frequent calls always cancelled older ones
		// so that we avoid doing this too often when the user is busy.
		// It is tempting to internalize this into Darla entirely, but
		// if so we need to make sure it is done in a way that is Mail
		// Beta-friendly because we call the throbberHack in a variety
		// of circumstances, not just for ads/beacons. -- kevykev

		if (( YAHOO.ads.darla._config == null ) ||
				( typeof YAHOO.ads.darla._config.throbberHack != "function" ))
			return;

		if ( delay === true ) // so callers can just say true
			delay = YAHOO.ads.darla.getConfigSetting ( "throbberDelay" );

		if ( typeof delay == "number" && delay > 0 ) {
		    if ( YAHOO.ads.darla._throbTimer != null )
		    	clearTimeout ( YAHOO.ads.darla._throbTimer );
		    YAHOO.ads.darla._throbTimer =  _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0)( "YAHOO.ads.darla._throbberHack()", delay );
			return;
		}

		if ( typeof YAHOO.ads.darla._config.throbberHack == "function" ) {
			YAHOO.ads.darla.log ( "letting loose the throbber hack", true );
			YAHOO.ads.darla._config.throbberHack();
		}
	},
	
	
	/**
	 * Get the URL to be used for an image beacon, from the config settings.
	 */
	_getBeaconUrl : function ( spaceid ) {

		// TODO: replace with ad-based CSC?  (Fetch an unscheduled position, like Z.)

		var url = YAHOO.ads.darla.getConfigSetting ( "beaconUrl" );
		if (( url == null ) || ( url == "" )) return null;

		return url + spaceid + "&t=" + Math.random();

	},


	/**
	 * Finish handler for ads handed off in the last ad call.  Builds ad HTML into their respective templates and updates elements and IFRAMEs on the page.
	 */
	renderHandoffs : function ( positions ) {

		var swapPositions = "";

		if ( YAHOO.ads.darla._handoffStore != null ) {

			YAHOO.ads.darla.log ( "rendering request: '" + YAHOO.ads.darla._lastEvent.settings.ps + "'" );


			YAHOO.ads.darla._renderStore = { };


			// TODO: HTML filtering
			//
			// This refers to something that YMail Beta did on some rare occasions: modify the ad HTML before
			// rendering it.
			//
			// The first case arose with an internal promo (not 3rd party ad), where we whacked on the HTML
			// to make something that was formatted for Classic appear more congruent with Beta's look and
			// feel.  In practice, this should NEVER happen with ads, but even there we had a case in Mail
			// Beta: we needed to convert some <P>'s to <DIV>'s to work around a Google toolbar bug that hit
			// Beta, but not Classic, with the exact same ads.  That particular case is now moot, but the general
			// idea being put forward here is that some properties might need to whack on ad-served content every
			// once in a while.  This is what the filterHtml config setting is intended for (but is not hooked up
			// anywhere yet).  Rather than expose this API, which invites abuse, perhaps instead individual
			// properties should modify their own copy of Darla, on a short-term basis, until their specific
			// problems are resolved.  In general modifying ad-served content is a bad idea.  -- kevykev 2007.05.02


			// ---- Scan for items rendered on the PHP, that we need to retrieve ourselves ----
			// TODO: having resolved some issues and bugs, this might no longer be necessary.
			// Current version of fc.php does not trigger this.
// TODO: I claim dead code.  Commenting out for now, should be stripped after an engineering review -- kevykev
//			var recvd = positions.split ( "," );
//
//			for ( var i=0; i<recvd.length; ++i ) {
//				var p = recvd[i];
//				if ( p.indexOf ( "!" ) == 0 ) {
//					YAHOO.ads.darla.log ( "retrieving ad from call-frame: " + p );
//					p = p.substring ( 1, p.length );
//					if ( YAHOO.ads.darla._copyRenderedAd ( p ) ) {
//
//						// see above: true means this will not be auto-swapped
//
//						if ( swapPositions.length > 0 )
//							swapPositions += ",";
//						swapPositions += p;
//					}
//				}
//			}


			// ---- For each ad, retrieve its template and insert the ad into the template

			// TODO: handling direct insertion without templates; should
			// the template prefix/postfix only apply to IFRAMEs?

			for ( var t in YAHOO.ads.darla._handoffStore ) {
				var d =  _proxy_jslib_handle(YAHOO.ads.darla._config.destinationMap, (t), 0, 0);
				YAHOO.ads.darla.log ( "found ad in handoff store: " + t );

				switch ( typeof d ) {
				case "string":
					YAHOO.ads.darla._updateTemplate ( t, 0, d );
					break;

				case "object":
					// we only ever create an array here
					for ( var i=0; i<d.length; (i= _proxy_jslib_assign_rval('++', 'i', '', '', i)) )
						YAHOO.ads.darla._updateTemplate ( t, i,  _proxy_jslib_handle(d, (i), 0, 0) );

					break;
				}
			}


			// ---- For each template, render it into its destination element

			for ( var t in YAHOO.ads.darla._renderStore ) {

				if ( YAHOO.ads.darla._renderTemplate ( t )) {
					
					// before the onload strategy was developed, we built
					// up a string of IDs and swapped all the elements at
					// once, after a timeout.  this technique is available
					// as an option, but perhaps it should go away.

					if ( swapPositions.length > 0 )
						swapPositions += ",";
					swapPositions += t;

				}
			}


			// TODO:
			// ---- Finally, look for failed ads and possibly hide their containers
			// not sure this makes sense

		// for the display:block/inline case, need to ignore anything being swapped
		//	var reqst = YAHOO.ads.darla._lastEvent.settings.ps.split ( "," );
		//	for ( var i=0; i<reqst.length; ++i ) {
		//		// make a hash
		//		reqst[reqst[i]] = true;
		//	}
		}


		if ( swapPositions.length > 0 )
			 _proxy_jslib_handle(null, 'setTimeout', setTimeout, 1, 0) ( 'YAHOO.ads.darla._swapElements ( "' + swapPositions + '" )', 100 );
	},


	/**
	 * Insert ad html into its template, possibly creating the template for the first time
	 *
	 * @param {String} pos Ad position name
	 * @param {Number} posIndex Which instance of the position is being updated
	 * @param {String} dest The template ID
	 */
	_updateTemplate : function ( pos, posIndex, dest ) {

		// We can get called multiple times for the same position,
		// because we can ask for multiple instances of the same ad.
		// The ad server will return as many as are available, which
		// may be fewer than we asked for.  Just bail if the ad html
		// is undefined.
		var ad =  _proxy_jslib_handle( _proxy_jslib_handle(YAHOO.ads.darla._handoffStore, (pos), 0, 0), (posIndex), 0, 0);
		if ( ad == null )
			return;

		// We retrieve the raw template only once.
		// There may be multiple substitutions per template, so we store
		// the original once, then update that one instance for every
		// substitution.

		if (  _proxy_jslib_handle(YAHOO.ads.darla._renderStore, ( dest ), 0, 0) == null ) {
			var h = YAHOO.ads.darla.getTemplate ( dest );
			if (( h == null ) || ( h == "" )) {
				var e =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( dest );
				if ( e && e.tagName.toLowerCase() == "iframe" )			
					var h = YAHOO.ads.darla.fillSimpleTemplate ( pos, ad );

				if ( h != null ) {
					 _proxy_jslib_assign('', YAHOO.ads.darla._renderStore , ( dest ), '=', ( h));
					// We're done, the simple template util took care of everything
					return;
				}

				// this is a plain ad (no template).  place it in the render store so we only have one place to look
				 _proxy_jslib_assign('', YAHOO.ads.darla._renderStore, ( dest ), '=', ( ad));
				return;
			}

			 _proxy_jslib_assign('', YAHOO.ads.darla._renderStore, ( dest ), '=', ( h));
			YAHOO.ads.darla.log ( "template found: " + pos + "->" + dest + ": " + h, true );
		}

		// HTML comments in the template tell us where to insert the ad HTML
		var h =  _proxy_jslib_handle(YAHOO.ads.darla._renderStore , ( dest ), 0, 0);
		 _proxy_jslib_assign('', YAHOO.ads.darla._renderStore , ( dest ), '=', (  _proxy_jslib_handle(h, 'replace', '', 1, 0) (new (RegExp) ( "<!-"+"-"+pos+"-"+"->", "" ), ad )));
	},


	/**
	 * Render a template into its destination element
	 *
	 * @param {String} tid The template ID
	 * @returns {Boolean} Returns true if this element needs the generic double-buffer swap handling
	 */
	_renderTemplate : function ( tid ) {

		var swap = false;

		var d = null;
		if ( !YAHOO.ads.darla._isSafari && YAHOO.ads.darla.getConfigSetting ( "doubleBuffering" ))
			d =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0)( tid + "_" );

		if ( d ) {

			// this is an element to be used for double-buffered rendering.
		
			if ( d.tagName.toLowerCase() == "iframe" ) {

				if ( YAHOO.ads.darla.getConfigSetting ( "fullDoubleBuffering" )) {

					// we attach a load handler to allow full rendering before
					// we show the new ad.

					if ( d.addEventListener ) {

						// TODO: detect and store any existing handler
						d.onload = YAHOO.ads.darla._iframeLoaded;

					// unfortunately, event listeners for iframe onload events don't fire on Gecko.
					// we have to use onload, above.  if it worked, it would look like this:
					//	d.removeEventListener ( "load", YAHOO.ads.darla._iframeLoaded, false );
					//	d.addEventListener ( "load", YAHOO.ads.darla._iframeLoaded, false );

					} else if ( d.attachEvent ) {

						d.detachEvent ( "onload", YAHOO.ads.darla._iframeLoaded );
						d.attachEvent ( "onload", YAHOO.ads.darla._iframeLoaded );
					}

				} else {

					// indicate that this won't be auto-swapped
					swap = true;
				}

			} else {

				// only iframes are auto-swapped
				swap = true;
			}

		} else {

			d =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0)( tid );
		}

		if ( d && d.tagName.toLowerCase() == "iframe" ) {

			var html =  _proxy_jslib_handle(YAHOO.ads.darla._renderStore , ( tid ), 0, 0);

			// Earlier we used to use document.write through a blank Iframe for Safari and (IE with different subdomain option)
			// and one more option was to write contents to the blank iframe through javascript:url technique
			// the main problems with these techniques are some adInterax richmedia ads would query for window.location and fail to show up
			// thus we use minidoc's generated from the fc.php whose purpose is to render an ad stored in the the parent document.
			
			var dm = YAHOO.ads.darla.getConfigSetting ( "domain" );
			YAHOO.ads.darla.log ( "rendering via minidoc for " + tid + ": " + html.length + " chars - " + html, true );
			if ( YAHOO.ads.darla._isIE )
				YAHOO.ads.darla._aboutToRewriteIframe ( d );
			YAHOO.ads.darla.loadMiniDocument(d, tid, dm);
		} else if ( d ) {
			 _proxy_jslib_assign('', d, 'innerHTML', '=', (  _proxy_jslib_handle(YAHOO.ads.darla._renderStore , ( tid ), 0, 0)));
		}
		return swap;
	},
	
	
	loadMiniDocument: function(iframe, adId, dm) {
		var url = YAHOO.ads.darla.getConfigSetting ( "callScript" )+"?md=true";
		if(dm)
			url+="&dh="+dm;
		var callFrame =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0)(YAHOO.ads.darla.getConfigSetting ( "callFrame" ));
		 _proxy_jslib_handle(callFrame, 'setAttribute', '', 1, 0)("minidoc", adId);		
		 _proxy_jslib_handle( _proxy_jslib_handle(iframe.contentWindow, 'location', '', 0, 0), 'replace', '', 1, 0)(url);
	},
	
	
	fetchAdForMiniDoc: function(adId) {
		return  _proxy_jslib_handle(YAHOO.ads.darla._renderStore , ( adId ), 0, 0);
	},	


	/**
	 * Blank an iframe in a safe way
	 *
	 * @param {String/IframeElement} The iframe, or id of an iframe, to be blanked.
	 */
	_blankIframe : function ( f ) {
		if ( typeof f == "string" )
			f =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( f );
		if (( f == null ) || ( f.tagName.toLowerCase() != "iframe" ))
			return;
			
		// make double-dog sure our handlers don't fire spuriously
		// (not to mention infinitely, since they might themselves
		// blank an iframe...)
		if ( f.onload == YAHOO.ads.darla._iframeLoaded )
			f.onload = null;
		else if ( f.detachEvent )
			f.detachEvent ( "onload", YAHOO.ads.darla._iframeLoaded );

		// empty it in a browser-history-safe way, with replace, and
		// use the special url that mitigates Discussion bar crashes
		// in IE; "about:blank" is the usual suspect for this, however
		// we avoid the discussion bar crash by using "javascript:''"
		// (empty document).  that url, however, causes security access
		// errors in Mozilla browsers when the page is refreshed.
		 _proxy_jslib_handle( _proxy_jslib_handle(f.contentWindow, 'location', '', 0, 0), 'replace', '', 1, 0) ( YAHOO.ads.darla._isIE ? "javascript:'<html></html>'" : "about:blank" );
	},


	/**
	 * Blank an iframe in prepration for rewriting its contents
	 *
	 * @param {String/IframeElement} The iframe, or id of an iframe, to be blanked.
	 */
	_aboutToRewriteIframe : function ( f ) {
		if ( typeof f == "string" )
			f =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( f );
		if (( f == null ) || ( f.tagName.toLowerCase() != "iframe" ))
			return;

		// empty it in a browser-history-safe way, with replace; also, a
		// possibly little-known trick: by issuing this statement, then
		// immediately (in the same JS execution thread) we can use document.write
		// inside this IFRAME and not incur a new entry in the browser history.
		// This works on IE and Firefox 1.0.  It broke on FF 1.5, but we don't need
		// to use this trick on that browser (we never use document.write there).
		 _proxy_jslib_handle( _proxy_jslib_handle(f.contentWindow, 'location', '', 0, 0), 'replace', '', 1, 0) ( "about:blank" );
	},


	/**
	 * Perform display swapping for double-buffered ad containers
	 */
	_swapElements : function ( positions ) {

		function swapElts ( id ) {
			var newElt =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( id + "_" );
			var oldElt =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( id );

			if ( newElt == null || oldElt == null ) return;

			newElt.id = id;
			newElt.style.display = "block";
			newElt.style.visibility = "visible";
			oldElt.id = id + "_";
			oldElt.style.display = "none";
			if ( oldElt.tagName.toLowerCase() == "iframe" )
				YAHOO.ads.darla._blankIframe ( oldElt );
			else
				 _proxy_jslib_assign('', oldElt, 'innerHTML', '=', ( ""));
		}

		YAHOO.ads.darla.log ( "swapping positions: " + positions, true );

		var ps = positions.split ( "," );
		for ( var i=0; i<ps.length; (i= _proxy_jslib_assign_rval('++', 'i', '', '', i)) ) {
			swapElts (  _proxy_jslib_handle(ps, (i), 0, 0) );
		}


		YAHOO.ads.darla._throbberHack( true );

	},


	/**
	 * The load handler for individual ad iframes.  Performs double-buffer swapping.
	 */
	_iframeLoaded : function ( event ) {
		var pos = null;

		if ( this.id ) {
			pos = this.id; // event is useless here, on Gecko
		} else if ( event && event.srcElement ) {
			pos = event.srcElement.id;
		}

		var d =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0) ( pos );
		if ( d.onload == YAHOO.ads.darla._iframeLoaded )
			d.onload = null;
		else if ( d.detachEvent )
			d.detachEvent ( "onload", YAHOO.ads.darla._iframeLoaded );

		YAHOO.ads.darla.log ( "frame loaded: " + pos, true );
		
		if ( pos.charAt ( pos.length - 1 ) == "_" )
			// this is a double-buffered render; swap it:
			YAHOO.ads.darla._swapElements ( pos.substring ( 0, pos.length-1 ) );

	},



	// TODO: Need an option for _loaded and _handoff to pass control to a
	// parent context, for apps like Candygram.


	
	/**
	 * Finishing callback for the ad fetching script.  Called at the end of the page,
	 * with info on which positions were updated.  Could also be called as the handoff
	 * point for an individual ad, in which case the second parameter is non-null.
	 *
	 * @param {String} positions Comma-delimited string of ad positions.  Interpretation
	 * varies on the second parameter.  When the second parameter exists, this is a string
	 * with one id, of the ad position which the HTML is associated with.  If the second
	 * parameter is not present (undefined), then the ad fetch is concluding and this is
	 * the list of positions successfully retrieved.
	 * @param {String} adHtml Optional parameter giving the html for one ad position.
	 */
	_loaded : function ( positions, adHtml ) {

		if ( adHtml != null ) {

			YAHOO.ads.darla.log ( "calling through to _handoff" );
			// this is a single ad being handed off
			return YAHOO.ads.darla._handoff ( positions, adHtml );

		}


		// Otherwise, this is the last call detailing all positions
		// that were successfully updated

		YAHOO.ads.darla.log ( "ads returned: '" + positions + "'" );

		YAHOO.ads.darla.renderHandoffs ( positions );

		YAHOO.ads.darla._startRotationTimer ();

		if ( YAHOO.ads.darla._config && YAHOO.ads.darla._config.finish )
			YAHOO.ads.darla._config.finish ( positions );
	},


	/**
	 * Standard "hand off" callback for the ad script to return ad HTML to this
	 * library.  Called on a per-position basis. The actual rendering takes place
	 * during the finish callback because we need to render some of them together.
	 *
	 * @param {String} position Position id of the ad html being handed off.
	 * @param {String} adHtml The html for one ad position.
	 */
	_handoff : function ( position, adHtml ) {
	
		YAHOO.ads.darla.log ( "ad hand-off: " + position + " - " + adHtml );

		if ( YAHOO.ads.darla._handoffStore == null )
			YAHOO.ads.darla._handoffStore = { };

		// an array, because we support multiple ads per position:
		if (  _proxy_jslib_handle(YAHOO.ads.darla._handoffStore, (position), 0, 0) == null )
			 _proxy_jslib_assign('', YAHOO.ads.darla._handoffStore, (position), '=', ( [ ]));


		var store =  _proxy_jslib_handle(YAHOO.ads.darla._handoffStore, (position), 0, 0);
		 _proxy_jslib_assign('', store, ( store.length ), '=', ( adHtml));

		return true;
	}

};


 ;
_proxy_jslib_flush_write_buffers() ;