/******************************************************************************
 The DM Object v1.5
 
 The DM Object inspired by SI Object (http://www.shauninman.com/).
 
 Stores a variety of functions localized to modules. Any module that requires
 initialization onload should have an onload handler. The DM.onload method will
 loop through all modules and run their respective onload handler. DM.onload
 can then be called in the window.onload event handler and all modules requiring
 initialization will be initialized. Does the same for onbeforeload and unload.
 
 v1.0 : Initial creation
 v1.1 : Added SideNav module
 v1.2 : Added Class, DynamicMap, EventsCalendar and FadeAnything modules
 v1.3 : Added SolutionFeatures module
 v1.4 : Added ParseLinks module
 v1.5 : Customised for Cunard
 
 ******************************************************************************/

if (!DM) { var DM = new Object(); };
DM.hasRequired 	= function() {
	if (document.getElementById && document.getElementsByTagName) {
		var html = document.getElementsByTagName('html')[0];
		html.className += ((html.className=='')?'':' ')+'has-dom';
		return true;
	};
	return false;
}();
DM.onbeforeload	= function() { if (this.hasRequired) { for (var module in this) { if (this[module].onbeforeload) { this[module].onbeforeload();	};};};};
DM.onload		= function() { if (this.hasRequired) { for (var module in this) { if (this[module].onload) { this[module].onload(); };};};};
DM.onunload		= function() { if (this.hasRequired) { for (var module in this) { if (this[module].onunload) { this[module].onunload(); };};};};


/******************************************************************************
 DM.SimulateSelectors module v1.2
 
 Adds CSS :first/last-child support for IE via classnames to unordered lists.
 
 v1.0: Initial creation
 v1.1: Added span with 'before' class and a pipe character and space list items
       in the footer element's list. Mimmicks the li's :before selector and the
       'content' property.
 v1.2: Added more complete support for :before/after pseudo selectors including
       getting the content property from the stylesheet.
 
 ******************************************************************************/
DM.SimulateSelectors = {
	onbeforeload		: function() {
		if (document.all) {
			var lists = document.getElementsByTagName('ul');
			
			for (var i=0; list=lists[i]; i++) {
				for (j=0; listItem=list.childNodes[j]; j++) {
					if (listItem.nodeName != 'LI') { continue; };
					if (j==0) { listItem.className += ((listItem.className=='')?'':' ')+'first'; };
					if (j==list.childNodes.length-1) { listItem.className += ((listItem.className=='')?'':' ')+'last'; };
				};
			};
			
			
			if (document.styleSheets) {
				var sheets = document.styleSheets, sl = sheets.length;
				
				for (var i=0; i<sl; i++) {
					var sheet = sheets[i];
					var rules = (currentSheet = sheet).rules, rl = rules.length;
					
					for (var j=0; j<rl; j++) {
						var rule = rules[j];
						var select = rule.selectorText, style = rule.style.cssText.replace(/; /g, ';\n') + ';', styleArr = style.split('\n'), sal = styleArr.length;
						
						if (style.indexOf('content:')!=-1 && select.indexOf('.clearfix')==-1) {
							for (var k=0; k<sal; k++) {
								if (styleArr[k].indexOf('content:')!=-1) {
									var content = styleArr[k].replace(/content: "([^"]+)";/, '$1');
									var affected = select.replace(/:(hover|active|unknown).*$/, '');
									var elements = this.getElementsBySelect(affected);
									
									for (var l=0; element=elements[l]; l++) {
										var b = document.createElement('span');
										b.className	= (select.indexOf('#xxx')!=-1)?'before':'after';
										b.innerHTML	= content;
										if (b.className=='before') {
											element.insertBefore(b, element.firstChild);
										} else {
											element.appendChild(b);
										};
									};
								};
							};
						};
					};
				};
			};
		};
	},
	getElementsBySelect	: function (rule) {
		var parts, nodes = [document];
		parts = rule.split(' ');
		
		for (var i=0; i<parts.length; i++) {
			nodes = this.getSelectedNodes(parts[i], nodes);
		};
		
		return nodes;
	},
	getSelectedNodes	: function (select, elements) {
		var result, node, nodes = [];
		var identify = (/\#([a-z0-9_-]+)/i).exec(select);
		
		if (identify) {
			var element = document.getElementById(identify[1]);
			return element? [element]:nodes;
		};
		
		var classname = (/\.([a-z0-9_-]+)/i).exec(select);
		var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
		var classReg = classname? new RegExp('\\b' + classname[1] + '\\b'):false;
		
		for (var i=0; i<elements.length; i++) {
			result = tagName? elements[i].all.tags(tagName):elements[i].all;
			for (var j=0; j<result.length; j++) {
				node = result[j];
				if (classReg && !classReg.test(node.className)) { continue; };
				nodes[nodes.length] = node;
			};
		};
		
		return nodes;
	}
};
	
	
/******************************************************************************
 DM.PrintWindow module v1.0
 
 ******************************************************************************/
DM.PrintWindow = function() {
	window.print?window.print():alert('Your browser doesn\'t support this funtion. Please select \'File > Print\' from your browser\'s menu to print this page.');
};
	
	
/******************************************************************************
 DM.SendToAFriend module v1.0
 
 ******************************************************************************/
DM.SendToAFriend = function(url) {
	var win = window.open(url, 'SendToAFriend', 'width=373, height=320');
	if (window.focus) { win.focus(); };
};


/******************************************************************************
 DM.Class module v1.0
 
 Provides helper functions for adding/removing/testing for classes.
 
 ******************************************************************************/
DM.Class = {
	add		: function (obj,cName) { this.kill(obj,cName); return obj && (obj.className+=(obj.className.length>0?' ':'')+cName); },
	kill	: function (obj,cName) { return obj && (obj.className=obj.className.replace(new RegExp("^"+cName+"\\b\\s*|\\s*\\b"+cName+"\\b",'g'),'')); },
	has		: function (obj,cName) { return (!obj || !obj.className)?false:(new RegExp("\\b"+cName+"\\b")).test(obj.className) }
};


/******************************************************************************
 DM.ParseLinks module v1.0
 
 Opens external links in a new window and adds classes to document type links
 (pdf, doc, etc) in the body content of the page.
 
 ******************************************************************************/
DM.ParseLinks = {
	page			: {contentid: 'content', navid: 'nav', tag: 'a'},
	onbeforeload	: function () {
		if (document.getElementById(this.page.contentid)) {
			var links = document.getElementById(this.page.contentid).getElementsByTagName(this.page.tag);
			
			for (i=0; link=links[i]; i++) {
				if (link.href&&link.parentNode.nodeName!='DD'&&link.parentNode.nodeName!='LI'&&(link.firstChild&&link.firstChild.nodeName!='IMG')) {
					var ext = String(link.href).substring(String(link.href).length, String(link.href).length - 3);
					if (ext=='pdf'||ext=='doc') {
						DM.Class.add(link, 'document-small');
						link.onclick = function() {
							window.open(this.href);
							return false;
						};
					/*} else if (link.href.indexOf('ibahealth.com')==-1) {
						DM.Class.add(link, 'external-small');
						link.onclick = function() {
							window.open(this.href);
							return false;
						};*/
					};
				};
			};
		};
		if (document.getElementById(this.page.navid)) {
			var links = document.getElementById(this.page.navid).getElementsByTagName(this.page.tag);
			
			for (i=0; link=links[i]; i++) {
				if (link.parentNode.nodeName=='LI' && link.href && link.href==document.location.href) { DM.Class.add(link.parentNode, 'active'); };
			};
		};
		if (document.getElementsByTagName) {
			var anchors = document.getElementsByTagName("a");
			for (var i=0; i<anchors.length; i++) {
				var anchor = anchors[i];
				if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") {
					anchor.target = "_blank";
					DM.Class.add(anchor, 'external');
				};
			};
		};
	}
};


/******************************************************************************
 DM.StyleSwitch module v1.0
 
 Manages the font size up/down feature.
 
 v1.0 : Initial creation
 
 ******************************************************************************/
DM.StyleSwitch = {
	preferred		: 'A-',
	fontsizeup		: function() {
		active = this.getActive();
		if (active == 'A--') {
			this.setActive('A-');
		} else if (active == 'A-') {
			this.setActive('A');
		} else if (active == 'A') {
			this.setActive('A+');
		} else if (active == 'A+') {
			this.setActive('A++');
		} else if (active == 'A++') {
			// Do nothing
		} else {
			this.setActive('A');
		};
	},
	fontsizedown	: function() {
		active = this.getActive();
		if (active == 'A++') {
			this.setActive('A+');
		} else if (active == 'A+') {
			this.setActive('A');
		} else if (active == 'A') {
			this.setActive('A-');
		} else if (active == 'A-') {
			this.setActive('A--');
		} else if (active == 'A--') {
			// Do nothing
		} else {
			this.setActive('A--');
		}
	},
	setActive		: function(title) {
		var i, a, main;
		for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
			if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
				a.disabled = true;
				if(a.getAttribute("title") == title) a.disabled = false;
			}
		}
	},
	getActive		: function() {
		var i, a;
		for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
			if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) return a.getAttribute("title");
		}
		return null;
	},
	createCookie	: function(name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		} else expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	},
	readCookie		: function(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	},
	onbeforeload	: function() {
		var cookie = this.readCookie("style");
		var title = cookie?cookie:this.preferred;
		if (title == 'null') { title = this.preferred; };
		this.setActive(title);
	},
	onload			: function() {
		var cookie = this.readCookie("style");
		var title = cookie?cookie:this.preferred;

		this.setActive(title);
	},
	onunload		: function() {
		var title = this.getActive();
		this.createCookie("style", title, 365);
	}
};


/******************************************************************************
 DM.Tabs module v1.1
 
 This library is copyright 2004 by Gavin Kistner, gavin@refinery.com
 It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt
 
 v1.0 : Imported Tabtastic code
 v1.1 : Rewrote the module to work within the DM Object
 
 TODO : Scrolling is already removed, but need to remove page offset code and add
        cookie to remember active tab in SetTabFromAnchor.
 
 ******************************************************************************/
DM.Tabs	= {
	tocTag				: 'ul',
	tocClass			: 'tabset-tabs',
	tabTag				: 'a',
	AddClass			: function (obj,cName) { this.KillClass(obj,cName); return obj && (obj.className+=(obj.className.length>0?' ':'')+cName); },
	KillClass			: function (obj,cName) { return obj && (obj.className=obj.className.replace(new RegExp("^"+cName+"\\b\\s*|\\s*\\b"+cName+"\\b",'g'),'')); },
	HasClass			: function (obj,cName) { return (!obj || !obj.className)?false:(new RegExp("\\b"+cName+"\\b")).test(obj.className) },
	FindEl				: function (tagName, evt) {
		if (!evt && window.event) evt=event;
		if (!evt) return DebugOut("Can't find an event to handle in DLTabSet::SetTab",0);
		var el=evt.currentTarget || evt.srcElement;
		while (el && (!el.tagName || el.tagName.toLowerCase()!=tagName)) el=el.parentNode;
		return el;
	},
	SetTabActive		: function (tab) {
		if (tab.tabTOC.activeTab) {
			this.KillClass(tab.tabTOC.activeTab,'active');
			if (tab.tabTOC.activeTab.tabContent) this.KillClass(tab.tabTOC.activeTab.tabContent,'tabset-content-active');
			//if (tab.tabTOC.activeTab.tabContent) tab.tabTOC.activeTab.tabContent.style.display='';
			if (tab.tabTOC.activeTab.prevTab) this.KillClass(tab.tabTOC.activeTab.previousTab,'pre');
			if (tab.tabTOC.activeTab.nextTab) this.KillClass(tab.tabTOC.activeTab.nextTab,'post');
			if (tab.tabTOC.activeTab==tab) {
				if (document.getElementById('content-top')) { document.getElementById('content-top').id = 'content-top-collapsed'; };
				tab.tabTOC.activeTab = null;
				return;
			};
		}
		this.AddClass(tab.tabTOC.activeTab=tab,'active');
		if (tab.tabContent) this.AddClass(tab.tabContent,'tabset-content-active');				
		//if (tab.tabContent) tab.tabContent.style.display='block';
		if (tab.prevTab) this.AddClass(tab.prevTab,'pre');
		if (tab.nextTab) this.AddClass(tab.nextTab,'post');
		if (document.getElementById('content-top-collapsed')) { document.getElementById('content-top-collapsed').id = 'content-top'; };
	},
	SetTabFromAnchor	: function (evt) {
		if (window.pageYOffset) {
			  pos = window.pageYOffset
		} else if (document.documentElement && document.documentElement.scrollTop) {
			pos = document.documentElement.scrollTop
		} else if (document.body) {
			  pos = document.body.scrollTop
		}
		//setTimeout('document.body.scrollTop='+document.body.scrollTop,1);
		setTimeout('window.scrollTo(0,'+pos+')',1);
		DM.Tabs.SetTabActive(DM.Tabs.FindEl('a',evt).semanticTab);
		this.blur();
		return false;
	},
	onbeforeload		: function () {
		window.everyTabThereIsById = {};
		
		var anchorMatch = /#([a-z][\w.:-]*)$/i,match;
		var activeTabs = [];
		
		var tocs = document.getElementsByTagName(this.tocTag);
		for (var i=0,len=tocs.length;i<len;i++){
			var toc = tocs[i];
			if (!this.HasClass(toc,this.tocClass)) continue;

			var lastTab;
			var tabs = toc.getElementsByTagName(this.tabTag);
			for (var j=0,len2=tabs.length;j<len2;j++){
				var tab = tabs[j];
				if (!tab.href || !(match=anchorMatch.exec(tab.href))) continue;
				if (lastTab){
					tab.prevTab=lastTab;
					lastTab.nextTab=tab;
				}
				tab.tabTOC=toc;
				everyTabThereIsById[tab.tabID=match[1]]=tab;
				tab.tabContent = document.getElementById(tab.tabID);
				
				if (this.HasClass(tab,'active')) activeTabs[activeTabs.length]=tab;
				
				lastTab=tab;
			}
			this.AddClass(toc.getElementsByTagName('li')[0],'first-child');
		}

		for (var i=0,len=activeTabs.length;i<len;i++){
			this.SetTabActive(activeTabs[i]);
		}

		for (var i=0,len=document.links.length;i<len;i++){
			var a = document.links[i];
			if (!(match=anchorMatch.exec(a.href))) continue;
			if (a.semanticTab = everyTabThereIsById[match[1]]) a.onclick = this.SetTabFromAnchor;
		}
		
		if ((match=anchorMatch.exec(location.href)) && (a=everyTabThereIsById[match[1]])) this.SetTabActive(a);
		
	}
};


/******************************************************************************
 DM.FadeAnything module v1.0
 
 Based on http://www.axentric.com/aside/fat/
 
 v1.0 : Imported Fat code
 
 ******************************************************************************/
DM.FadeAnything = {
	make_hex	: function (r,g,b) {
		r = r.toString(16); if (r.length == 1) { r = '0' + r; };
		g = g.toString(16); if (g.length == 1) { g = '0' + g; };
		b = b.toString(16); if (b.length == 1) { b = '0' + b; };
		return "#" + r + g + b;
	},
	fade_all	: function () {
		var a = document.getElementsByTagName("*");
		for (var i = 0; i < a.length; i++) {
			var o = a[i];
			var r = /fade-?(\w{3,6})?/.exec(o.className);
			if (r) {
				if (!r[1]) { r[1] = ""; };
				if (o.id) { this.fade_element(o.id,null,null,"#"+r[1]); };
			};
		};
	},
	fade_element : function (id, fps, duration, from, to) {
		if (!fps) { fps = 30; };
		if (!duration) { duration = 3000; };
		if (!from || from=="#") { from = "#FFFFD9"; };
		if (!to) { to = this.get_bgcolor(id); };
		
		var frames = Math.round(fps * (duration / 1000));
		var interval = duration / frames;
		var delay = interval;
		var frame = 0;
		
		if (from.length < 7) { from += from.substr(1,3); };
		if (to.length < 7) { to += to.substr(1,3); };
		
		var rf = parseInt(from.substr(1,2),16);
		var gf = parseInt(from.substr(3,2),16);
		var bf = parseInt(from.substr(5,2),16);
		var rt = parseInt(to.substr(1,2),16);
		var gt = parseInt(to.substr(3,2),16);
		var bt = parseInt(to.substr(5,2),16);
		
		var r,g,b,h;
		while (frame < frames) {
			r = Math.floor(rf * ((frames-frame)/frames) + rt * (frame/frames));
			g = Math.floor(gf * ((frames-frame)/frames) + gt * (frame/frames));
			b = Math.floor(bf * ((frames-frame)/frames) + bt * (frame/frames));
			h = this.make_hex(r,g,b);
		
			setTimeout("DM.FadeAnything.set_bgcolor('"+id+"','"+h+"')", delay);

			frame++;
			delay = interval * frame; 
		};
		setTimeout("DM.FadeAnything.set_bgcolor('"+id+"','"+to+"')", delay);
	},
	set_bgcolor : function (id, c) {
		var o = document.getElementById(id);
		o.style.backgroundColor = c;
	},
	get_bgcolor : function (id) {
		var o = document.getElementById(id);
		while(o) {
			var c;
			if (window.getComputedStyle) { c = window.getComputedStyle(o,null).getPropertyValue("background-color"); };
			if (o.currentStyle) { c = o.currentStyle.backgroundColor; };
			if ((c != "" && c != "transparent") || o.tagName == "BODY") { break; };
			o = o.parentNode;
		}
		if (c == undefined || c == "" || c == "transparent") { c = "#FFFFFF"; };
		var rgb = c.match(/rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/);
		if (rgb) { c = this.make_hex(parseInt(rgb[1]),parseInt(rgb[2]),parseInt(rgb[3])); };
		return c;
	}
};


/******************************************************************************
 window.onload/onunload()
 
 This should only ever require DM.onload()/onunload() which in turn initialises
 all modules that require it.
 
 ******************************************************************************/
window.onload	= function() { DM.onload(); };
window.onunload	= function() { DM.onunload(); };