// Need this for JQuery intellisense
/// <reference path="jquery-1.2.6-vsdoc.js" />

// Ensure the NewMind ETWP namespaces are defined
NewMind.registerNameSpace("NewMind.TunbridgeWells.env");
NewMind.registerNameSpace("NewMind.TunbridgeWells.ControlData");

//common.js

function AddEventListener(obj, type, action) {
	NewMind.dom.addEventListener(obj, type, action);
}

function GetEventSource(pthis) {
	if (!document.all) {
		//.. moz
		var x = pthis;
	} else {
		//.. ie
		var x = window.event.srcElement;
	}
	return x;
}

function returnFalse(e) {
	var ev = e || window.event;
	if (ev.preventDefault) {
		ev.preventDefault();
	} else {
		ev.returnValue = false;
	}
}

function findAncestorNode(el, strAncestorNode, strAncestorClassName) {
	var ancestorNode = el;
	do {
		ancestorNode = ancestorNode.parentNode;
	}
	while (ancestorNode.nodeName.toLowerCase() != strAncestorNode.toLowerCase() && ancestorNode.className != strAncestorClassName)
	return ancestorNode;
}

// iefix.js


function iefix() {
	// this fix is for ie patch causing usability issue with embedded flash objects
	try {
		objects = document.getElementsByTagName("object");
		for (var i = 0; i < objects.length; i++) {
			if (objects[i].className == 'iefix') {
				objects[i].outerHTML = objects[i].outerHTML;
			}
		}
	}
	catch (e) { }
}

AddEventListener(window, 'load', iefix);

/* SOURCE FILE: AnchorPosition.js */
function getAnchorPosition(anchorname) { var useWindow = false; var coordinates = new Object(); var x = 0, y = 0; var use_gebi = false, use_css = false, use_layers = false; if (document.getElementById) { use_gebi = true; } else if (document.all) { use_css = true; } else if (document.layers) { use_layers = true; } if (use_gebi && document.all) { x = AnchorPosition_getPageOffsetLeft(document.all[anchorname]); y = AnchorPosition_getPageOffsetTop(document.all[anchorname]); } else if (use_gebi) { var o = document.getElementById(anchorname); x = AnchorPosition_getPageOffsetLeft(o); y = AnchorPosition_getPageOffsetTop(o); } else if (use_css) { x = AnchorPosition_getPageOffsetLeft(document.all[anchorname]); y = AnchorPosition_getPageOffsetTop(document.all[anchorname]); } else if (use_layers) { var found = 0; for (var i = 0; i < document.anchors.length; i++) { if (document.anchors[i].name == anchorname) { found = 1; break; } } if (found == 0) { coordinates.x = 0; coordinates.y = 0; return coordinates; } x = document.anchors[i].x; y = document.anchors[i].y; } else { coordinates.x = 0; coordinates.y = 0; return coordinates; } coordinates.x = x; coordinates.y = y; return coordinates; }
function getAnchorWindowPosition(anchorname) { var coordinates = getAnchorPosition(anchorname); var x = 0; var y = 0; if (document.getElementById) { if (isNaN(window.screenX)) { x = coordinates.x - document.body.scrollLeft + window.screenLeft; y = coordinates.y - document.body.scrollTop + window.screenTop; } else { x = coordinates.x + window.screenX + (window.outerWidth - window.innerWidth) - window.pageXOffset; y = coordinates.y + window.screenY + (window.outerHeight - 24 - window.innerHeight) - window.pageYOffset; } } else if (document.all) { x = coordinates.x - document.body.scrollLeft + window.screenLeft; y = coordinates.y - document.body.scrollTop + window.screenTop; } else if (document.layers) { x = coordinates.x + window.screenX + (window.outerWidth - window.innerWidth) - window.pageXOffset; y = coordinates.y + window.screenY + (window.outerHeight - 24 - window.innerHeight) - window.pageYOffset; } coordinates.x = x; coordinates.y = y; return coordinates; }
function AnchorPosition_getPageOffsetLeft(el) { var ol = el.offsetLeft; while ((el = el.offsetParent) != null) { ol += el.offsetLeft; } return ol; }
function AnchorPosition_getWindowOffsetLeft(el) { return AnchorPosition_getPageOffsetLeft(el) - document.body.scrollLeft; }
function AnchorPosition_getPageOffsetTop(el) { var ot = el.offsetTop; while ((el = el.offsetParent) != null) { ot += el.offsetTop; } return ot; }
function AnchorPosition_getWindowOffsetTop(el) { return AnchorPosition_getPageOffsetTop(el) - document.body.scrollTop; }

function ElementScrollTo(objEleSrc) {
	// Ensure scroll function and image element available
	if ((!window.scroll) || (!objEleSrc))
		return false;

	// Ensure we can retrieve image position
	var intImageStart = AnchorPosition_getWindowOffsetTop(objEleSrc);
	if (isNaN(parseInt(intImageStart)))
		return false;

	// If need to scroll, leave some space above image
	var OFFSET_TOP = 16;

	// Ensure we can retrieve image height, window scroll pos and viewable area's height
	var intImageHeight = parseInt(objEleSrc.height);
	if (isNaN(intImageHeight) || (intImageHeight <= 0) && !isNaN(objEleSrc.offsetHeight))
		intImageHeight = parseInt(objEleSrc.offsetHeight);
	var intScrollPosY = GetScrollPosY();
	var intViewHeight = GetViewHeight();
	if (isNaN(intImageHeight) || (intImageHeight <= 0)
	|| (intScrollPosY == null)
	|| (intViewHeight == null)) {
		// If not, scroll to image anyway and return success
		var intScrollToY = intImageStart - OFFSET_TOP;
		if (intScrollToY < 0)
			intScrollToY = 0;
		scroll(0, intScrollToY);
		return true;
	}

	// As all info was available, only scroll if image not fully in view
	var intImageEnd = intImageStart + intImageHeight;
	if ((intScrollPosY > intImageStart) || (intScrollPosY + intViewHeight < intImageEnd)) {
		var intScrollToY = intImageStart - OFFSET_TOP;
		if (intScrollToY < 0)
			intScrollToY = 0;
		scroll(0, intScrollToY);
	}
	return true;

	function GetScrollPosY() {
		var intScrollY = null;
		if (document.all) {
			if (!document.documentElement.scrollTop)
				intScrollY = document.body.scrollTop;
			else
				intScrollY = document.documentElement.scrollTop;
		}
		else
			intScrollY = window.pageYOffset;
		if (isNaN(parseInt(intScrollY)))
			intScrollY = null;
		return intScrollY;
	}

	function GetViewHeight() {
		if (document.documentElement && document.documentElement.clientWidth) {
			return document.documentElement.clientHeight;
		}
		else if (document.body) {
			return document.body.clientHeight;
		}
		return null;
	}
}



// =========================================================================================
// TRANSLATE PIXEL DIMENSIONS INTO EMs
// - USED BY InitMapSearch AND InitItineraryDetails
// =========================================================================================
NewMind.TunbridgeWells.GetRelativeSizeFromPixels = function(strPixels) {
	// This function tested at varying dpi settings with IE6, IE7, Opera 9.24, Firefox
	// 2.0.0.14, Safari 3.0.4 - it should hold true for all.

	// Ensure we've got a valid input - a dimension specified in pixels (eg. "16px")
	// If not, throw back out whatever we got passed in.
	if (!strPixels)
		return strPixels;
	strPixels = String(strPixels);
	if (strPixels.length < 3)
		return strPixels;
	if (strPixels.substring(strPixels.length - 2).toUpperCase() != "PX")
		return strPixels;
	var intPixels = parseInt(strPixels, 10);
	if (isNaN(intPixels))
		return strPixels;

	// Although zooming is handled automatically by IE7 (and Opera and Firefox 3, etc..) if all
	// dimensions on a page are specified in ems but an image specified with pixel dimensions
	// then chances are the native-zooming done by the browser will work when viewed at
	// standard (96) dpi but - confirmed by IE7 at least - we need to convert pixels to ems
	// such that the browser can make the dpi adjustment itself if viewing at other than
	// 96, such that the image still matches other "em" measurements.

	// This conversion requires the element in question to have font-size:100% - this may
	// require css work if, for example, the body has a font-size:90% setting.
	return (intPixels / 16) + "em";
};



// =========================================================================================
// CODE TO APPLY "ScriptEnabled" TO THE ENTERPRISE CONTROL PREVIOUS TO THE "Content (Free
// Text)" CONTROL THAT CALLS THIS FUNCTION.
// =========================================================================================
function ControlScriptEnablerInit(bPrevCtrl) {
	// Generate a random id and create an element with it, otherwise we won't be
	// able to work out where in the DOM we are.
	var strId = "ElScriptEnabler" + parseInt(Math.random() * 1000000000);
	document.write("<div id=\"" + strId + "\"><!-- --></div>");
	var fncEnable = function() { Enable(bPrevCtrl); };
	setTimeout(fncEnable, 1);
	return;

	function Enable(bPrevCtrl) {
		// Optional boolean parameter: default false
		if ((typeof (bPrevCtrl) === "undefined") || (bPrevCtrl !== true))
			bPrevCtrl = false;

		// Try to access the element we generated
		var objEle = document.getElementById(strId);
		if (!objEle)
			return;

		// Try to access the div.sys_control parent
		var objEleCtrl = findAncestorNode(objEle, "div", "sys_control");
		if (!objEleCtrl)
			return;

		// Try to retrieve previous control within same container
		if (bPrevCtrl) {
			objEleCtrl = PreviousSibling(objEleCtrl);
			if (!objEleCtrl)
				return;
		}

		// Apply "ScriptEnabled" class to this controls's first level descendents,
		// if not already set
		if (!objEleCtrl.hasChildNodes())
			return;
		for (var intIndex = 0; intIndex < objEleCtrl.childNodes.length; intIndex++)
			ApplyScriptClass(objEleCtrl.childNodes[intIndex]);
		return;

		function ApplyScriptClass(objEle) {
			if (IsTextNode(objEle))
				return;
			var strScriptEnabled = "ScriptEnabled";
			var strClass = objEle.className;
			if ((" " + strClass + " ").indexOf(" " + strScriptEnabled + " ") === -1)
				strClass = strClass + " " + strScriptEnabled;
			objEle.className = strClass;
		}
		function PreviousSibling(objEle) {
			// Try to retrieve previous sibling for an element, skipping any text nodes
			while (1) {
				objEle = objEle.previousSibling;
				if (!objEle)
					return null;
				if (!IsTextNode(objEle))
					return objEle;
			}
		}
		function IsTextNode(objEle) {
			return ((!objEle) || (typeof (objEle.tagName) === "undefined") || (objEle.tagName === "!"));
		}
	}
}


// =========================================================================================
// HANDLE EXTERNAL / POPUP LINKS
// - To be fully XHTML, link elements shouldn't utilise the "target" attribute, so it's
//   been taken out of the generated markup and instead we hook up the click and keypress
//   handlers to popup a window for us on links with "rel" attrib set to "external".
//    However, this means that "referrer" header information isn't passed properly by all
//   browsers (IE) so stats get screwed up. "target" is still a valid DOM setting, so we're
//   going to cheat and make the click and keypress handlers set "target" to "_blank" and
//   let the window open, then undo the "target" setting (so even Firebug's little indicator
//   in the status bar will flip back to valid).
// NB: "rel" attributes can have multiple values, space separated - eg. "external nofollow"
// =========================================================================================
function externalLinks() {
	// Loop through all anchor / link elements of page with "rel" attrib set to "external"
	// and adjust intercept their onclick handler (if any) such that it will call the
	// TargetAttribCheat function first, which will set the link's "target" attrib to
	// "blank" and then set it back to its previous value (if any) 100ms later. This
	// means any onclick code that gets called better be quicker! Displaying an alert
	// box in the onclick handler will cause issues, for example.
	if (!document.getElementsByTagName)
		return;
	var arrLinks = document.getElementsByTagName("a");
	for (var i = 0; i < arrLinks.length; i++) {
		var objLink = arrLinks[i];
		if ((objLink.getAttribute("href"))
		&& ((" " + objLink.getAttribute("rel") + " ").indexOf(" external ") !== -1)) {
			// 2008-07-16 DWR: Removed this "opens in new window" link - better off generating
			// this as part of the title on the server-side (usinng languages.xml content)
			//objLink.title += " Link opens in a new window";
			objLink.onclick = GenNewFunc(
				TargetAttribCheat,
				(typeof (objLink.onclick) === "undefined") ? null : objLink.onclick);
		}
	}

	// This methods returns a function wrapping old and new onclick handlers
	function GenNewFunc(fncNew, fncOld) {
		// When we get here (see above), we'll have a reference to the containing element
		// which we don't want in the click handler (circular references issue for garbage
		// collection in IE), so we'll explicitly set objLink to null here.
		var objLink = null;
		return function() {
			fncNew.apply(this, arguments);
			if (fncOld != null)
				return fncOld.apply(this, arguments);
		};
	}

	// This method temporarily assigns "_blank" value to "target" attribute, then resets
	// it back after a delay
	function TargetAttribCheat(e, bEnable, bAutoDisable, intAutoDisTimeout) {
		// Try to access the source element that raised this call
		e = e || window.event;
		if (!e)
			return;
		var objSrc = e.srcElement || e.target;
		if (!objSrc)
			return;

		// If we've got an image within the link element then that image may appear as the
		// source element, rather than the actual link. So we may need to head up the chain
		// until we get the original anchor.
		while (String(objSrc.tagName).toUpperCase() !== "A") {
			// Check we've not hit the top of the tree
			if ((!objSrc) || (objSrc.parentNode === objSrc))
				return;
			objSrc = objSrc.parentNode;
		}

		/*
		bEnable, bAutoDisable and intAutoDisTimeout are optional, defaulting
		to True, True and 100, respectively.
		bEnable:
		True => Set "target" attrib to "_blank"
		False => Reset to previous value
		bAutoDisable:
		True => After a timeout, automatically re-call this method with bEnable
		set to False to reset the "target" attribute's value. Only relevant when
		bEnable is True.
		intAutoDisTimeout:
		Override the default AutoDisable timeout. Only applicable when bEnable
		and bAutoDisable are True.
		*/
		if ((typeof (bEnable) === "undefined") || (bEnable !== false))
			bEnable = true;
		if ((typeof (bAutoDisable) === "undefined") || (bAutoDisable !== false))
			bAutoDisable = true;
		if ((typeof (intAutoDisTimeout) === "undefined") || isNaN(intAutoDisTimeout))
			intAutoDisTimeout = 100;
		Work(objSrc, bEnable, bAutoDisable, intAutoDisTimeout);

		// Perform the element manipulation
		function Work(objSrc, bEnable, bAutoDisable, intAutoDisTimeout) {
			if (bEnable) {
				// In case this method gets called several times in succession, don't allow
				// a previously recorded "target" value to be overwritten.
				if ((typeof (objSrc.targetOldNM) === "undefined") || (objSrc.targetOldNM === null)) {
					if (typeof (objSrc.target) === "undefined")
						objSrc.targetOldNM = "";
					else
						objSrc.targetOldNM = objSrc.target;
				}
				// Set new "target" value and set up AutoDisable function (if required)
				objSrc.target = "_blank";
				if (bAutoDisable)
					setTimeout(function() { Work(objSrc, false); }, intAutoDisTimeout);
			}
			else {
				if (typeof (objSrc.targetOldNM) !== "undefined") {
					// Reset old .target value and delete .targetOldNM backup value.
					// NB: IE(6?) doesn't seem to like this - so on error just set to null instead.
					objSrc.target = objSrc.targetOldNM;
					try { delete objSrc["targetOldNM"]; }
					catch (e) { objSrc.targetOldNM = null; }
				}
			}
		}
	}
}
AddEventListener(window, 'load', externalLinks);

// =========================================================================================
// GET QUERYSTRING DATA FROM CURRENT URl
// 2009-04-08: This has been moved to core.js but ETWP references not updated yet, so set
//             up an alis
// =========================================================================================
NewMind.TunbridgeWells.GetQuerystringData = NewMind.GetQuerystringData;

/*
Helper Function to allow you to get a control's position / key - this is the key of the control in the page, not the controlkey
*/
NewMind.TunbridgeWells.GetControlKey = function(node) {
	// 2009-02-23 DWR: Changed this from the RegEx approach (still below, but commented out) to
	// a straight-forward split and seek job. The RegEx was failing and I hate them so much I'm
	// not convinced it was worth the time to find out what was wrong!
	var nodeClass = String($(node).attr('class'));
	var arrSegments = nodeClass.split(" ");
	var iControlKey = 0;
	for (iIndex = 0; iIndex < arrSegments.length; iIndex++) {
		var strSegment = arrSegments[iIndex];
		if (strSegment.substring(0, 1) === "c") {
			strSegment = strSegment.substring(1, strSegment.length);
			var iKey = parseInt(strSegment, 10);
			if (!isNaN(iKey)) {
				iControlKey = iKey;
				break;
			}
		}
	}

	/*
	var arrayControlClass = Number(nodeClass.match(/(?:\D)(\d+)/));
	if (arrayControlClass != NaN) {
	iControlKey = arrayControlClass[1]; //arrayControlClass matches c{number} and then {number}
	}
	*/

	return iControlKey;
};

/**
* custom way of getting hover effects - mainly for IE6
*/
NewMind.TunbridgeWells.MouseOver = function() {
	return {
		init: function(sSelector) {
			$(sSelector).mouseover(function() {
				$(this).addClass('ie-hover');
			}).mouseout(function() {
				$(this).removeClass('ie-hover');
			});
		}
	};
} ();


/*
*	Adding TabSwitcher Helpers to Common as these MUST always be available
*/
NewMind.TunbridgeWells.TabSwitcherHelpers = function() {
	return {
		//if you need to know if your element is in a tab control
		IsInTabControl: function($control) {
			//if we don't pass a jQuery object here drop out this is an error
			if (typeof ($control.jquery) === "undefined") {
				return;
			}

			var bIsInTabControl = false;

			if (typeof (NewMind.TunbridgeWells.TabSwitcher) !== "undefined") { //see if the tabs switcher JS is around
				//see if this jQuery object has a parent thats a tabs control
				bIsInTabControl = $control.parents("div.ctl_Tabs").length > 0;
			}
			return bIsInTabControl;
		},

		/**
		* Rather than each control implementing the the following in each JS file just call this
		* how to use example - NewMind.TunbridgeWells.TabSwitcherHelpers.CheckForTabReSize($node); $node is a jQuery object
		*/
		CheckForTabReSize: function($control) {
			//if we don't pass a jQuery object here drop out
			if (typeof ($control.jquery) === "undefined") {
				return;
			}
			if (typeof (NewMind.TunbridgeWells.TabSwitcher) !== "undefined") { //see if the tabs switcher JS is around
				//see if this jQuery object has a parent thats a tabs control
				var $tabContainer = $control.parents("div.ctl_Tabs");
				if ($tabContainer.length > 0) {
					//if so we need to get its control key
					var tabVariableName = 'tabs' + NewMind.TunbridgeWells.GetControlKey($tabContainer[0]);
					//find it in our ActiveTabSwitchers
					var tabToResize = NewMind.TunbridgeWells.ActiveTabSwitchers[tabVariableName];
					//if we have the tab then call its ResizeContainer method
					if (typeof (tabToResize) !== "undefined") {
						tabToResize.ResizeContainerFromJQueryObject($control);
					}
				}
			}
		}

		/**
		*	Bind a callback to the loaded event of an elements/control's parent tab control
		*/
		
//MJ this isn't working - timing is causing problems
//		SubscribeToParentTabsLoadingEvent: function($control, callback) {
//			var $tabContainer = $control.parents("div.ctl_Tabs");
//			if ($tabContainer.length > 0) {
//				//if so we need to get its control key
//				var tabVariableName = 'tabs' + NewMind.TunbridgeWells.GetControlKey($tabContainer[0]);				
//				//find it in our ActiveTabSwitchers
//				var tabToResize = NewMind.TunbridgeWells.ActiveTabSwitchers[tabVariableName];
//				//if we have the tab then subscribe our call back to the loaded event
//				if (typeof (tabToResize) !== "undefined") {
//					tabToResize.TabControlLoaded.subscribe(callback);
//				}
//			}
//		}
	};
} ();


/**
* Ajax Forms JS
*/
NewMind.TunbridgeWells.AjaxForms = function() {
	var doPostBack = function(node) {
		//turn our node into a jQuery object
		var $node = $(node);
		var postbackURL = $node.attr('action');
		//find our node's parent syscontrol wrapper
		var $parentSysContainer = $node.parents('div.sys_control');
		//get our control key from this wrapper
		var iControlKey = NewMind.TunbridgeWells.GetControlKey($parentSysContainer);
		//build a postbackURL using the control key
		var URL = postbackURL + "?PartialRenderType=html&PartialRenderControlList=" + iControlKey;
		$.ajax({
			type: 'post',
			url: URL,
			data: $node.serialize(),
			success: function(data) {
				//upon success replace the html of our parent syscontrol with the html returned
				$parentSysContainer.html($(data).html());
				NewMind.TunbridgeWells.TabSwitcherHelpers.CheckForTabReSize($node);
				return false;
			},
			error: function() {
				//if an error occurs fall back to normal form submit
				$node.find('form').unbind('submit').submit();
			}
		});

	};
	return {
		postback: function(node) {
			doPostBack(node);
			return false;
		}
	};
} ();

/**
* ColumnResizer
* @Requires JQuery.1.2.6
*/
NewMind.TunbridgeWells.ColumnResizer = function() {
	//private vars

	//private methods

	var resizeCols = function(sSelectors) {
		var iHeight = 0;
		$(sSelectors).each(function() {
			if ($(this).height() > iHeight) {
				iHeight = $(this).height();
			}
		}).height(iHeight);
	};

	return {
		init: function() {

		},

		/**
		* resize columns
		* @param {Object} sSelectors - selector of columns to resize
		*/
		resize: function(sSelectors) {
			resizeCols(sSelectors);
		}
	};

} ();

/**
* 2 ColumnMaker
* @Requires JQuery.1.2.6
*/
NewMind.TunbridgeWells.TwoColumnMaker = function() {
	//private vars

	//private methods
	/**
	* Takes a container and breaks its items into two columns based on each item's h3
	*/
	var makeCols = function(sContainer) {
		var $items = $(sContainer);
		var $parent = $items.parent();
		$parent.append('<div class="oddColumn"></div><div class="evenColumn"></div>'); //create columns

		// Pull out the odd entries into one column..
		$items.find("h3:odd").each(function(i) { //for each odd h3
			var $this = $(this);
			var $objChild = $this.next();
			$parent.find('.oddColumn').append($this).append($objChild);
		});
		
		$items.find("h3").each(function(i) { //for each even h3
			var $this = $(this);
			var $objChild = $this.next();
			$parent.find('.evenColumn').append($this).append($objChild);
		});

		$items.remove();

	};

	/*
	*Takes a container and breaks its items into 2 columns based on the break position
	*/
	var makeCols2 = function(sSelector, sParent, breakPosition, offset) {

		var $items = $(sSelector); //stash items away

		var $parent = $(sParent);
		$parent.empty();

		if (offset > 0) {
			$parent.append($items.slice(0, offset)); // readd any items we aren't putting into columns
		}

		$parent.append('<div class="oddColumn"></div><div class="evenColumn"></div>'); //create columnds

		$parent.find('.oddColumn').append($items.slice(offset, breakPosition));
		$parent.find('.evenColumn').append($items.slice(breakPosition, $items.length));
	};

	return {
		init: function() {

		},

		/**
		* resize columns
		* @param {Object} sSelectors - selector of content to make into columns
		* @param {int} iColumns - number of columns to make
		*/
		makeCols: function(sContainer) {
			makeCols(sContainer);
		},

		makeCols2: function(sSelector, sParent, breakPosition, offset) {
			makeCols2(sSelector, sParent, breakPosition, offset);
		}
	};
} ();
