/*
	common js for every page.
*/

/* bp.navigation.js ***********************************************************************************************************************************************************/

if ( window.bp == undefined )
	bp = { };

(function(){
	var $ = glow.dom.get;
	
	var ref = {
		w_h: ["/cbbc/bluepeter/", "Home"],
		w_h_p: ["/cbbc/bluepeter/presenters/", "Presenters"],
		w_h_b: ["/cbbc/bluepeter/central/", "Blue Peter Central"],
		w_h_a: ["/cbbc/bluepeter/adventurelands/", "Adventure Lands"],
		w_h_c: ["/cbbc/bluepeter/viparea/", "<acronym title='Very Important Person'>VIP</acronym> Area"],
		w_h_f: ["/cbbc/bluepeter/factbytefactory/", "Factbyte Factory"],
		w_h_e: ["/cbbc/bluepeter/episodes/", "Episodes"]
	};
	var topNavID = '.bp-topnav';
	var leftNavID = '.cbbc-lhn';
	var currentView = null;
	var hasFlash = ( swfobject.hasFlashPlayerVersion("9.0.0") );
	var title = document.title;
	
	var setHash = function(value)
	{
		var hash = "#";
		if ( value == "w_h")
		{
			if ( window.location.hash == "" ) {
				return;
			}
		}
		else {
			hash = "dl=" + value
		}
		window.location.hash = hash;
		// ie adds fragment to title wierdly when flash is present
		setTimeout(function(){document.title = title},0);
	}
	
	bp.navigation = {
		topNav: null, 
		leftNav: null,
		flashMov: "bp_flash",
		init: function(){
			var current;
			if(window.location.pathname == "/cbbc/bluepeter/"){
				current	= (window.location.href.indexOf('?dl=') != -1) ? window.location.href.split('?dl=')[1] : "w_h";
				if ( window.location.hash.indexOf("dl=") > -1 ) {
					current = window.location.hash.split('dl=')[1];
				}
				this.setSelected(current);
				currentView = current;
			}
			this.topNav = $(topNavID);
			this.leftNav = $(leftNavID);
			this.setEventHandlers();
			this.animateLeftNav();
		},
		clickHandler: function(target){
			if(target.tagName.toLowerCase() == "a" && target.id){
				if(currentView != target.id){
					if(bp.navigation.getFlashInstance(bp.navigation.flashMov) != undefined){
						this.getFlashInstance(this.flashMov).changeView(target.id);
					}
					this.setSelected(target.id);
					currentView = target.id;
				}
			}
		},
		setSelected: function(target){
			var cV;
			if(currentView){
				cV = currentView;
			} else {
				cV = "w_h";
			}
			gCV = $("#"+cV);
			var txt = gCV.text();
			gCV.replaceWith("<a id='"+cV+"' href='"+ref[cV][0]+"'>"+ref[cV][1]+"<span class='nav-bot'><!-- --></span></a>");
			$("#"+target).replaceWith("<p id='"+target+"'>"+ref[target][1]+"<span class='nav-bot'><!-- --></span></p>");
			if( hasFlash && !window.htmlOnly ) {
				setHash(target);
			}
		},
		change: function(value){
			// Checks that value is not the current view and is one of the top level sections.
			if(value == currentView) return;
			var tnVal;
			for (var i in ref){
				if(i == value){
					tnVal = value;
				}				
			}
			if(tnVal == undefined) return;
			if(bp.navigation.getFlashInstance(bp.navigation.flashMov) == undefined) return;
			if(currentView != null){
				var cV = $("#"+currentView);
				var txt = cV.text();
				cV.replaceWith("<a id='"+currentView+"' href='"+ref[currentView][0]+"'>"+ref[currentView][1]+"</a>");
			} else {
				var cV = $("#w_h");
				var txt = cV.text();
				cV.replaceWith("<a id='w_h' href='"+ref["w_h"][0]+"'>"+ref["w_h"][1]+"</a>");
			}
			$('#'+value).replaceWith("<p id='"+value+"'>"+ref[value][1]+"</p>");
			currentView = value;
			if( hasFlash && !window.htmlOnly ) {
				setHash(value);
			}
		},
		animateLeftNav: function(){
			var nav = this.leftNav;
			if(nav.length == 0) return;
			var h1 = nav.get('h1');
			var primary_lis = nav.get('ul.primary > li');
			var initTop = -100;
			var currentY = 0;
			primary_lis.each(function(i){
				this == primary_lis[i];
				var itm = $(primary_lis[i]);
				itm.css("position", "absolute");
				//Gloader bug in Safari when you go back to the page
				glow.anim.css(itm, 3, {
					"top" : {from: initTop+"px", to: currentY+"px"}
				}, {tween: glow.tweens.overshootOut()}).start();
				var children = itm.get("ul.secondary");
				if(children.length > 0){
					children.css("display", "none");
					var childH = 0;
					children.css("position", "relative");
					children.css("display", "block");
					childH = children.height();
					glow.anim.css(children, 3, {
						"height" : {from: 0+"px", to: childH+"px"}
					}, {tween: glow.tweens.overshootOut()}).start();
				}
				currentY = currentY + itm.height(); 
			});
		},
		setEventHandlers: function(){
			// Add click event to the navigation
			var topNav = this.topNav;
			glow.events.addListener(
				'acronym',
				'click',
				 function (e) { e.stopPropagation(); }
			);
			glow.events.addListener(
				topNav, 
				'click',
				function(e){
					// Behaviour is dependent on whether flash is enabled
					if(bp.navigation.getFlashInstance(bp.navigation.flashMov) != undefined){
						if ( e.source.id != "w_h_e" && e.source.id != "w_h_chat" )
						{
							bp.navigation.clickHandler(e.source);
							e.preventDefault();
						}
					}
				}
			);
		},
		setTopNavClassName: function(val){
			this.topNavClassName = val;
		},
		setLeftNavClassName: function(val){
			this.leftNavClassName = val;
		},
		getFlashInstance: function(movieName){
			if (navigator.appName.indexOf("Microsoft") != -1) {
				return window[movieName];
			} else {
				return document[movieName];
			}
		}
	}
})();
glow.ready(function(){
	if (glow.isSupported) {
		bp.navigation.init();
	}
});


/* bp.lbstub.js ***************************************************************************************************************************************************************/

/*
	from back in the day before gloader, when we were scraping all the bytes we could get. this handles launching lightboxes.
	on the first call, it loads the main lightbox script
*/

if ( window.bp == undefined )
	bp = {};
if ( bp.utils == undefined )
	bp.utils = {};
if ( bp.widgets == undefined )
	bp.widgets = {};

/*
	If glow is present in the page we include a couple of classes use by the lightbox.
*/
if ( window.glow )
{
	/*
		bp.utils.swf is helper class for detecting + hiding flash
		We hide all flash in the page whenever a lightbox is launched, to prevent bugs in ff/mac z-ordering + for
		performance reasons
	*/
	bp.utils.swf = function()
	{
		var flashUrlTest = /.swf($|\?)/i,
			hiddenFlash = [],
			$ = glow.dom.get;
		
		var U = function() {};
		/*
		Method: hasFlash
			Test if elements contain one or more flash embeds.
			
		Arguments:
			root - (selector|DOMElement|NodeList) the element to check. Defaults to document.
			ignore - (selector|DOMElement|NodeList) flash inside this are ignored. Defaults to null.
		*/
		U.hasFlash = function(root, ignore)
		{
			return U.getFlash(root || document, ignore).length > 0;
		},
		
		/*
		Method: getFlash
			Returns NodeList of flash elements inside root
			
		Arguments:
			root - (selector|DOMElement|NodeList) the element to check. Defaults to document.
			ignore - (selector|DOMElement|NodeList) flash inside this are ignored. Defaults to null.
		*/
		U.getFlash = function(root, ignore)
		{
			root = root || document;
			var flash = new glow.dom.NodeList();
			
			$("object, embed").each(function() {
				var that = this;
				//we need to use getAttribute here because Opera & Safari don't copy the data to properties
				if (
					(that.getAttribute("type") == "application/x-shockwave-flash" ||
					flashUrlTest.test(that.getAttribute("data") || that.getAttribute("src") || "") ||
					(that.getAttribute("classid") || "").toLowerCase() == "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000") &&
					(ignore == null || !$(that).isWithin(ignore) )
				) {
					flash.push([that]);
				}
			});
			return flash;
		},
		
		/*
		Method: hideFlash
			Hides flash embeds beneath root
			
		Arguments:
			root - (selector|DOMElement|NodeList) the element to check. Defaults to document.
			ignore - (selector|DOMElement|NodeList) flash inside this are ignored. Defaults to null.
		*/
		U.hideFlash = function(root, ignore)
		{
			//return if they've already been hidden, saves time
			if (hiddenFlash.length) { return; }
			var i = 0;
			
			U.getFlash(root || document, ignore).each(function() {
				var that = this;
				hiddenFlash[i++] = [that, that.style.width, that.style.height, that.style.visibility];
				that.style.width = "1px";
				that.style.height = "1px";
				if ( !glow.env.ie )
					that.style.visibility = "hidden";
			});
		},
		/*
		Method: revertFlash
			Reshow flash elements hidden with hideFlash
		*/
		U.revertFlash = function()
		{
			for (var i = 0, len = hiddenFlash.length; i < len; i++)
			{
				hiddenFlash[i][0].style.height = hiddenFlash[i][2];
				hiddenFlash[i][0].style.width = hiddenFlash[i][1];
				if ( !glow.env.ie )
					hiddenFlash[i][0].style.visibility = hiddenFlash[i][3];

			}
			hiddenFlash = [];
		}
		
		return U;
	}();
	
	/*
		bp.widgets.Mask below is a copy of glow.widgets.Mask with some alterations
		It's copied here rather than extended so that it can be opened immediately without requiring the ~30k widgets.js
		Also displays a loading graphic, hides _all_ flash in the background and uses a generated PNG for translucent mask in ff/mac
		to prevent flash flicker bug.
	*/
	bp.widgets.utils = function() {
		var doc,
			docBody,
			env = glow.env;
		
		glow.ready(function() {
			doc = document;
			docBody = doc.body;
			
			//check if css or images are disabled, add class name "glow-basic" to body if they aren't
			var testDiv = glow.dom.create('<div class="glow-cssTest"></div>').appendTo(docBody);
			if (testDiv.css("z-index") != "1234" || testDiv.css("background-image").indexOf("ctr.png") == -1) {
				docBody.className += " glow-basic";
			}
			testDiv.remove();
			//add some IE class names to the body to help widget styling
			env.ie && (docBody.className += " glow-ie");
			//note: we apply the class "glow-ielt7" for IE7 if it's in quirks mode
			(env.ie < 7 || !env.standardsMode) && (docBody.className += " glow-ielt7");
			//some rounding issues in firefox when using opacity, so need to have a workaround
			env.gecko && (docBody.className += " glow-gecko");
			
		});
		
		
		return {
			/*
			PrivateMethod: _scrollPos
				Get the scroll position of the document. Candidate for moving into glow.dom?
			*/
			_scrollPos: function() {
				var win = window,
					docElm = env.standardsMode ? doc.documentElement : docBody;
				
				return {
					x: docElm.scrollLeft || win.pageXOffset || 0,
					y: docElm.scrollTop || win.pageYOffset || 0
				};
			},
			_windowSize: function()
			{
				var w = 0, h = 0;
				if( typeof( window.innerWidth ) == 'number' )
				{
					//Non-IE
					w = window.innerWidth;
					h = window.innerHeight;
				}
				else if ( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) )
				{
					//IE 6+ in 'standards compliant mode'
					w = document.documentElement.clientWidth;
					h = document.documentElement.clientHeight;
				}
				else if ( document.body && ( document.body.clientWidth || document.body.clientHeight ) )
				{
					//IE 4 compatible
					w = document.body.clientWidth;
					h = document.body.clientHeight;
				}
				
				return {width:w, height:h};
			}
		};
	}();
	
	bp.widgets.Mask = function() {
		var dom = glow.dom,
			$ = dom.get,
			env = glow.env,
			events = glow.events,
			widgets = bp.widgets.utils,
			bodyProperties, //this is a holding place for body padding & margins
			htmlStr = '<div class="glowNoMask" style="margin:0;padding:0;position:absolute;width:100%;top:0;left:0;overflow:auto;', //reusable html string
			noScrollContainer,
			iframeSrc = '<iframe class="glowNoMask" style="margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);display:none"></iframe>',
			utils = bp.utils.swf,
			doFlashFix = ( navigator.platform.indexOf("Mac") != -1
				&& ( navigator.userAgent.indexOf("Firefox") != -1 || navigator.vendor.indexOf("Camino") != -1 ) );
		
		
		function Mask(opts) {
			this._isOpen = false;				
			
			this.opts = glow.lang.apply({
				color: '#000',
				opacity: 0.7,
				zIndex: 9900,
				disableScroll: false,
				onlyOne:true
			}, opts || {});
			
			// if ff/camino + mac: use data uri png as background to fix opacity bug
			if ( doFlashFix )
			{
				// default grey png if canvas isn't available
				var data = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGDYBAAAtwCz7B/12wAAAABJRU5ErkJggg==";

				// draw canvas with mask opacity + color + get base64 data uri
				var canvas = document.createElement("canvas");
				if ( !!canvas )
				{
					canvas.width = canvas.height = 1;
					var context = canvas.getContext("2d");
					if ( !!context && !!canvas.toDataURL )
					{
						var c = dom.parseCssColor(this.opts.color);
						context.fillStyle = "rgba(" + c.r + ", " + c.g + ", " + c.b + ", " + this.opts.opacity + ")";
						context.fillRect(0,0,1,1);
						data = canvas.toDataURL("image/png");
					}
				}
				this.opts.color = "url("+data+")";
				this.opts.opacity = 1.0;
			}
			
			/*
			Property: maskElement
				The node overlayed to create the mask. Access this if you want to
				change its properties on the fly
			*/
			var docBody = document.body,
				mask = this.maskElement = dom.create(
				htmlStr + 'z-index:' + this.opts.zIndex + ';background:' + this.opts.color + ';visibility:hidden"></div>'
			).appendTo(docBody),
				that = this;
			
			if ( !!this.opts.loading )
			{
				this.loading = this.opts.loading.css("position", "absolute").css("z-index", this.opts.zIndex+1).css("display", "none").appendTo(docBody);
			}
			
			mask.css("opacity", this.opts.opacity);
			
			if (glow.env.ie < 7) {
				this._iframe = dom.create(iframeSrc).css("z-index", this.opts.zIndex - 1).appendTo(docBody);
			}
			
			//add mask node click event, route it through to a Mask event
			events.addListener(mask, "click", function() {
				events.fire(that, "click");
			});
			if (this.opts.onClick) {
				events.addListener(this, "click", opts.onClick);
			}
		}

		Mask.prototype = {
			hideLoading: function() {
				this.loading.css("display", "none");
			},
			
			showLoading: function() {
				this.loading.css("display", "block");
			},
			
			/*
			Method: add
				Displays the mask.
			*/
			add: function (showLoading) {
				if ( this._isOpen )
					return;
				
				var doc = $(document),
					body = $(document.body),
					win = bp.widgets.utils._windowSize(),
					that = this;
				
				glow.events.fire(bp.widgets.Mask, "open");
				
				this._isOpen = true;
				function resizeMask() {
					var bodyHeight = body.height(),
						bodyWidth = body.width();
					for (var i = 0; i < 2; i++) {
						that.maskElement.css("width", "100%").
								  css("height", Math.max(bodyHeight, win.height) + "px");
					}
					if ( !!that.loading )
						positionLoading();
					
					if (glow.env.ie < 7) {
						var maskStyle = that.maskElement[0].style;
						that._iframe.css("width", maskStyle.width).css("height", maskStyle.height);
					}
				}
				
				function positionLoading()
				{
					var useFixed = (!env.ie && !(env.webkit < 522)) || (env.ie > 6 && env.standardsMode),
						extraOffset = useFixed ? {x:0,y:0} : widgets._scrollPos();
						
					if ( useFixed )
						that.loading.css("position", "fixed");
						
					that.loading.css("top", (win.height - that.loading.height()) / 2 + extraOffset.y + "px");
					that.loading.css("left", (win.width - that.loading.width()) / 2 + extraOffset.x + "px");
				}
				
				utils.hideFlash(document);
				
				this.maskElement.css("visibility", "visible");
				this.maskElement.css("display", "block");
				if ( showLoading )
					this.showLoading();
				if (glow.env.ie < 7) {
					this._iframe.css("display", "block");
				}
				resizeMask();
				this._resizeListener = events.addListener(window, "resize", resizeMask);
				if ( showLoading ) {
					this._scrollListener = events.addListener(window, "scroll", positionLoading);
				}
			},

			/*
			Method: remove
				Removes the mask.
			*/
			remove : function () {
				if ( !this._isOpen )
					return;
				this._isOpen = false;
				if ( !!this.loading )
					this.hideLoading();
				this.maskElement.css("visibility", "hidden");
				this.maskElement.css("display", "none");
				if (glow.env.ie < 7) {
					this._iframe.css("display", "none");
				}
				glow.events.removeListener(this._resizeListener);
				glow.events.removeListener(this._scrollListener);
				
				utils.revertFlash();
				
				glow.events.fire(bp.widgets.Mask, "close");
				
			}
		};

		return Mask;
	}();
}


/*
	Stub code for Lightbox.
	Should be included on every page which wants to link to content in a lightbox
	If glow or jstools is on the page, this file should be included after them
	
	
*/
bp.lbstub = function()
{
	var suffix = ( bp.suffixes && bp.suffixes.script ) ? bp.suffixes.script : "";
	var lbScriptUrl = "/cbbc/bluepeter/script/bp.lb" + suffix + ".js";			// Path to the main LB code

	
	/*
		Detect if the browser's up to the job.
		glow.isSupported only seems to return false if we are in IE + jScript version is < 1.5
		Here we test if the browser can handle XHR
	*/
	var isSupported = (function()
	{
		var ua = navigator.userAgent.toLowerCase(),
			nanArray = [0, NaN],
			opera = Number((/opera[\s\/]([\d\.]+)/.exec(ua) || nanArray)[1]),
			ie = opera ? NaN : Number((/msie ([\d\.]+)/.exec(ua) || nanArray)[1]);
			
		if ( window.location.pathname.indexOf("/lb/") > -1 )
			return false;
		
		if ( window.glow )
		{
			if ( !glow.isSupported )
				return false;
		}
		if (window.XMLHttpRequest) {
			return true;
		} else if (ie < 7) {
			var progIds = ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP'];
			for (var i = 0, len = progIds.length; i < len; i++) {
				try {
					new ActiveXObject(progIds[i]);
					return true;
				} catch(e) { }
			}
		}
		return false;
	})();
	
	var fail = function(url)
	{
		url = [url, (url.indexOf("?") >= 0 ? "&" : "?"), "lb_fail=1"].join("");
		window.location.assign(url);
	};
	
	var R = {};
	var isWindowLoaded = false;
	
	/*
		If browser's not up to it, we return a basic object
	*/
	if ( !isSupported )
	{
		R = {
			isSupported:false,
			redirect:function(){},
			launchClickListener:function(){},
			launchOrRedirect: fail
		};
		/*
			main code from bp.lb.js isn't on this page yet so we temporarily map our methods to the bp.lb space
		*/
		if ( !bp.lb )
			bp.lb = bp.lbstub;
		return R;
	}
	
	
	var init = function()
	{
		/*
			Add styles requried for basic glow.widgets functionality.
			This must be kept up-to-date if we update our glow version
		*/
		var css = [".glow-cssTest {", 
						"background: url('//www.bbc.co.uk/glow/0.4.1/dist/widgets/images/darkpanel/ctr.png');",
						"position: absolute;",
						"visibility: hidden;",
						"z-index: 1234;",
					"}",
					".glow-overlay {",
					"	visibility: hidden;",
					"	display: none;",
					"	overflow: hidden;",
					"	position: absolute;",
					"}"].join("");
		R.addStyleSheet(css);
		
		/*
			
		*/
		if ( window.location.hash )
		{
			var loadLbNow = function()
			{
				var hash = window.location.hash;
				if ( hash.indexOf("#") === 0 )
					hash = hash.substring(1);
				var url = "/cbbc/bluepeter" + hash;
				R.launch(url);
			};
			if ( isWindowLoaded )
				loadLbNow();
			else
				glow.events.addListener(window, "load", loadLbNow);
		}
	}
	
	R = {
		isSupported:true,
		mask:null,
		
		/*
			Called at the very top of LB alternative page (in /include/lb/base_redirect.sssi)
			
			EG:
			launchURL - URL of page which should launch current LB EG: "/cbbc/games"
			contentPath: Path of LB content within /contentinclude. EG: "games/play/beattheboss"
		*/
		redirect: function(launchUrl, contentPath)
		{
			var query = ( !!window.location.search ) ? window.location.search : "";
			if ( query.indexOf("dbg=1" ) >=0 || query.indexOf("lb_fail=1") >= 0 )
				return;
			window.location = launchUrl + query + "#/lb/" + contentPath;
		},
		
		
		/*
			Adds a stylesheet to the page containing css
		*/
		addStyleSheet: function(css)
		{
			var elem = document.createElement("style");
			document.getElementsByTagName("head")[0].appendChild(elem);
			if ( !!elem.styleSheet )
				elem.styleSheet.cssText = css;
			else
			{
				var textNode = document.createTextNode(css);
				elem.appendChild(textNode);
			}
			
			return elem;
		},
		
		/*
			Add a click handler to all links. Don't use glow cos it might not be available
		*/
		addHandlersToAllAnchors: function()
		{
			R.addHandlerToAnchors("body");
		},
		
		addHandlerToAnchors: function(parentEl)
		{
			glow.dom.get(parentEl).get("a").each(function()
			{
				R.addHandlerToAnchor(this);
			});
		},
		
		addHandlerToAnchor: function(el)
		{
			glow.events.addListener(el, "click", function(e)
			{
				if ( bp.lb.launch(e.attachedTo.href) )
					e.preventDefault();
			});
		},
		
		// utility. returns hash of url components
		splitUrlToParts: function(sourceUri)
		{
			var uriPartNames = ["source","protocol","authority","domain","port","path","directoryPath","fileName","query","anchor"],
				uriParts = new RegExp("^(?:([^:/?#.]+):)?(?://)?(([^:/?#]*)(?::(\\d*))?)((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[\\?#]|$)))*/?)?([^?#/]*))?(?:\\?([^#]*))?(?:#(.*))?").exec(sourceUri),
				uri = {};
			
			for(var i = 0; i < 10; i++){
				uri[uriPartNames[i]] = (uriParts[i] ? uriParts[i] : "");
			}
			
			/* Always end directoryPath with a trailing backslash if a path was present in the source URI
			Note that a trailing backslash is NOT automatically inserted within or appended to the "path" key */
			if(uri.directoryPath.length > 0){
				uri.directoryPath = uri.directoryPath.replace(/\/?$/, "/");
			}
			
			return uri;
		},
		
		// returns hash of useful data if the url describes a lightbox. or null
		getDataFromUrl: function(url)
		{
			var re = /\/lb\/([^?#\n\s]+)(.*)/,
				urlParts = R.splitUrlToParts(url),
				obj,
				match;

			match = re.exec(url);
			if ( !!match )
			{
				obj = {
					lbPath: "/lb/" + match[1],
					path: "/cbbc/bluepeter",
					query: urlParts.query
				};
			}
			return obj;
		},
		
		/*
			Called from SWFs to test any URL for Lightboxyness + launch if appropriate
			or just head to the url otherwise
		*/
		launchOrRedirect: function(url)
		{
			if ( url.constructor == Array )
				url = url[0];
			if ( url.constructor == Array )
				url = url[0];
			if ( !R.launch(url) )
				window.location.assign(url);
			return true;
		},
		
		
		launchClickListener: function(e)
		{
			var el = glow.dom.get(e.source);
			while ( !!el.parent() && !el.is("a") )
			{
				el = el.parent();
			}
			if ( el.is("a") )
			{
				if ( el.hasAttr("href") && R.launch(el.attr("href")) )
				{
					e.preventDefault();
				}
			}
		},
		
		fail: fail,
		
		launch: function(url, opts)
		{
			
			var o = R.getDataFromUrl(url);
			// not a lightboxy url
			if ( !o ) {
				//	alert('not a lightboxy url');
				return false;
			}
			//try
			//{
				// load lightbox script if needed
				if ( !bp.lb.isLoaded )
				{
					R.mask = new bp.widgets.Mask({
						loading:glow.dom.create("<img src='/cbbc/bluepeter/img/f/lb/loading.gif' width='122' height='41' />")
					});
					R.mask.add(true);
					
					glow.net.loadScript(lbScriptUrl,{
						useCache: true
					});
					R.executeWhenLoaded(bp.lbstub.launch, null, [url, opts], "bp", "bp.lb", "bp.lb.isLoaded" );
					return true;
				}
				// lb script is loaded, call the main launch method
				bp.lb.launch(url, opts);

			/*}
			catch(e)
			{
				R.fail(url);
			}*/
			return true;
		},
		
		/*
			Runs func in funcScope with funcArgs when all other parameters are defined
		*/ 
		executeWhenLoaded: function(func, funcScope, funcArgs)
		{
			var intRef, argRef = arguments;
			function executeCheck()	{
				// for loop starts at 1 to skip the function argument.
				for (var i = 3; i<argRef.length; i++){
					var test = false;
					eval( "test = window." + argRef[i]);
					if ( !test ){
						if (!intRef) intRef = setInterval(executeCheck,50);      
						return;
					}
				}
				clearInterval(intRef);
				func.apply(funcScope, funcArgs); // only reaches here when for loop is satisfied.
			}
			executeCheck();
		}
	}
	
	if ( window.glow )
	{
		glow.events.addListener(window, "load", function(){isWindowLoaded = true;});
		glow.ready(init);
	}
	
	// back in the day before glow.ready did anything useful
	if ( window.blqOnDomReady )
		blqOnDomReady(function(){R.addHandlersToAllAnchors(); });
		
	
	/*
		main code from bp.lb.js isn't on this page yet so we temporarily map our methods to the bp.lb space
	*/
	if ( !bp.lb )
		bp.lb = R;
	return R;
}();