/**/
function getLayer( strID )
{
	if( document.all && !window.opera )
		return document.all[ strID ];
	else
		return document.getElementById( strID );
}
function setClass(element, className) {
	if(element == null || className == null) {
		return;
	}
	if(document.all && !window.opera) {
		element.className = className;
	} else{
		element.setAttribute("class", className);
	}
}
function removeClass(element) {
	if(element == null) {
		return;
	}
	if(document.all && !window.opera) {
		element.className = "";
	} else{
		element.removeAttribute("class");
	}
}
function getClassName(element) {
	if(element == null) {
		return "";
	}
	var className = document.all && !window.opera ? element.className : element.getAttribute("class");
	return className == null ? "" : className;
}
function addEvent(obj, eventType, func, useCaption)
{
	if (!obj || !eventType || !func) {
		return false;
	} else if (obj.addEventListener) {
		obj.addEventListener(eventType, func, useCaption);
		return true;
	} else if (obj.attachEvent) {
		var retVal = obj.attachEvent("on"+eventType, func);
		return retVal;
	} else {
		return false;
	}
}
// Class MSFlyout, Constructor
function MSFlyout(/*String*/ id, /*int*/ type) {
	this.id = id;
	this.type = type;
	this.active = false;
	
	// Get Layer for this Flyout
	if (id) {
		this.flyout = getLayer(id);
	}

	// Check and extend global MSFlyout list if necessary
	if (!MSFlyout.flyouts[type]) {
		MSFlyout.flyouts[type] = new Array();
	}

	// Add flyout to global MSFlyout object
	MSFlyout.flyouts[type][id] = this;
	
	// Add event listener for this flyout
	if (this.flyout) {
		addEvent(this.flyout, "mouseover", function() { MSFlyout.flyouts[type][id].activate() }, true);
		addEvent(this.flyout, "mouseout", function() { MSFlyout.flyouts[type][id].deactivate() }, true);
	}
}
// Static Flyout Types
MSFlyout.TYPE_CORENAV1 = 1;
MSFlyout.TYPE_CORENAV2 = 2;
MSFlyout.TYPE_PCN_BUTTON = 3;
MSFlyout.TYPE_PCN_MENU = 4;
MSFlyout.TYPE_METANAVLOGIN = 5;
// Static Timeout Settings
MSFlyout.ACTIVATION_TIMEOUT = new Array();
MSFlyout.ACTIVATION_TIMEOUT[MSFlyout.TYPE_CORENAV1] = 200;
MSFlyout.ACTIVATION_TIMEOUT[MSFlyout.TYPE_CORENAV2] = 500;
MSFlyout.ACTIVATION_TIMEOUT[MSFlyout.TYPE_PCN_BUTTON] = 200;
MSFlyout.ACTIVATION_TIMEOUT[MSFlyout.TYPE_PCN_MENU] = 250;
MSFlyout.ACTIVATION_TIMEOUT[MSFlyout.TYPE_METANAVLOGIN] = 250;
MSFlyout.DEACTIVATION_TIMEOUT = new Array();
MSFlyout.DEACTIVATION_TIMEOUT[MSFlyout.TYPE_CORENAV1] = 200;
MSFlyout.DEACTIVATION_TIMEOUT[MSFlyout.TYPE_CORENAV2] = 200;
MSFlyout.DEACTIVATION_TIMEOUT[MSFlyout.TYPE_PCN_BUTTON] = 200;
MSFlyout.DEACTIVATION_TIMEOUT[MSFlyout.TYPE_PCN_MENU] = 200;
MSFlyout.DEACTIVATION_TIMEOUT[MSFlyout.TYPE_METANAVLOGIN] = 200;
// Static CSS Settings
MSFlyout.CSS_CLASS_ACTIVE = "ms-active";
MSFlyout.CSS_CLASS_HOVER = "ms-fly-hover";
// Static Vars
MSFlyout.flyouts = new Array();
MSFlyout.openFlyout = new Array();
MSFlyout.changeTimeout = new Array();
MSFlyout.closeTimeout = new Array();
// Static Methods
MSFlyout.change = function(/*String*/ id, /*int*/ type) {
	// Close open MSFlyout Menu
	if (MSFlyout.openFlyout[type]) {
		MSFlyout.openFlyout[type].handleDeactivate();
	}
	
	// Open new MSFlyout Menu
	if (MSFlyout.flyouts[type][id]) {
		MSFlyout.flyouts[type][id].handleActivate();
	}
}
MSFlyout.closeAll = function(/*int*/ type) {
	// Close all open MSFlyout Menus
	for (var flyout in MSFlyout.flyouts[type]) {
		if (MSFlyout.flyouts[type][flyout].active) {
			MSFlyout.flyouts[type][flyout].handleDeactivate();
		}
	}
	
	// Reset openFlyout Reference
	MSFlyout.openFlyout[type] = undefined;
}
MSFlyout.pushClass = function(object, className) {
	var /*String*/ objClasses = getClassName(object);
	if (objClasses.indexOf(className) == -1) {
		objClasses += " " + className;
	}
	setClass(object, objClasses);
}
//push class for the MetaNavigation
MSFlyout.pushClassMN = function(object) {
	object.style.display = "block";
}
MSFlyout.popClass = function(object, className) {
	var /*String*/ objClasses = getClassName(object);
	var /*int*/ posClassName = objClasses.indexOf(className);
	if (posClassName != -1) {
		if (posClassName + className.length < objClasses.length) {
			objClasses = objClasses.substring(0, posClassName) + objClasses.substring(posClassName + className.length);
		} else {
			objClasses = objClasses.substring(0, posClassName);
		}
	}
	setClass(object, objClasses);
}
//pop class for the MetaNavigation
MSFlyout.popClassMN = function(object) {
	object.style.display = "none";
}
// Methods
MSFlyout.prototype.activate = function() {
	// Clear Closing Timeout
	clearTimeout(MSFlyout.changeTimeout[this.type]);
	clearTimeout(MSFlyout.closeTimeout[this.type]);

	// Closing all independend, open menus
	for (var type in MSFlyout.openFlyout) {
		var /*boolean*/ isIndependend = true;
		switch (this.type) {
			// Core Navigation flyouts
			case MSFlyout.TYPE_CORENAV1:
			case MSFlyout.TYPE_CORENAV2:
				isIndependend = ((type != MSFlyout.TYPE_CORENAV1)
						&& (type != MSFlyout.TYPE_CORENAV2));
				break;
			
			// PCN Flyouts
			case MSFlyout.TYPE_PCN_BUTTON:
			case MSFlyout.TYPE_PCN_MENU:
				isIndependend = ((type != MSFlyout.TYPE_PCN_BUTTON)
						&& (type != MSFlyout.TYPE_PCN_MENU));
				break;
			
			case MSFlyout.TYPE_METANAVLOGIN:
		}
		
		// If current flyout type is independend and has open flyouts, close them
		if (isIndependend && MSFlyout.openFlyout[type]) {
			MSFlyout.closeAll(type);
		}
	}

	if (MSFlyout.openFlyout[this.type] == undefined) {
		// If no MSFlyout Menu is open, strictly open the current one
		this.handleActivate();
	} else if (MSFlyout.openFlyout[this.type] != this) {
		MSFlyout.changeTimeout[this.type] = setTimeout("MSFlyout.change(\"" + this.id + "\", \"" + this.type + "\")", MSFlyout.ACTIVATION_TIMEOUT[this.type]);
	}
}
MSFlyout.prototype.handleActivate = function() {
	// Call Ajax Request for Core Navigation 2 Flyout
	if (this.type == MSFlyout.TYPE_CORENAV2) {
		var /*String[]*/ values = this.id.split("@");
		var /*String*/ elementId = values[0];
		var /*String*/ handle = values[1];
		ms_corenav_loadFlyoutData(elementId, handle);
	} else {
		ms_setIFrameHeight(this.flyout.id);
	}
	
	
	// Activate MSFlyout
	if (this.type == MSFlyout.TYPE_METANAVLOGIN) {
		this.active = true;
		MSFlyout.pushClassMN(this.flyout);
	}
	else {
		this.active = true;
		MSFlyout.pushClass(this.flyout, MSFlyout.CSS_CLASS_HOVER);
	}
	
	// Set openFlyout Reference
	MSFlyout.openFlyout[this.type] = this;
	
	// Only for PCN and SUBNAVIGATION
	if (this.type == MSFlyout.TYPE_PCN_BUTTON || this.type == MSFlyout.TYPE_PCN_MENU) {
		if (this.flyout && this.flyout.getElementsByTagName("div") && 
				this.flyout.getElementsByTagName("div").length > 0) {
			// Check for IE
			var isIE = (document.all && !window.opera);
			
			// Calculate flyoutTop position
			var flyoutOffset = 0;
			var flyoutMenu = this.flyout.getElementsByTagName("div")[0];
			if (flyoutMenu.lastChild && flyoutMenu.lastChild.childNodes.length > 0) {
				var childNodes = flyoutMenu.lastChild.childNodes;
				for (var i = 0; i < childNodes.length; i++) {
					if (childNodes[i].nodeName == "LI") {
						flyoutOffset += childNodes[i].offsetHeight;
					}
				}
			}

			// Get positions of page elements			
			var buttonTop = getAbsTop(this.flyout);
			var footerHeight = getLayer("ms-footer").offsetHeight;
			if (isIE) {
				var innerHeight = document.documentElement.clientHeight - footerHeight;
				var pageOffset = document.documentElement.scrollTop;
			} else {
				var innerHeight = window.innerHeight - footerHeight;
				var pageOffset = window.pageYOffset;
			}
			
			// Check if flyout menu would be visibile
			var lowestY = buttonTop + flyoutOffset - pageOffset;
			if (lowestY > innerHeight) {
				// Set position from the button
				flyoutMenu.style.bottom = "0px";
				flyoutMenu.style.top = "auto"; // need to overwrite!
				
				// IE needs a height for the outer element to work correctly
				if (isIE && this.flyout) {
					this.flyout.style.height = this.flyout.offsetHeight + "px";
				}
			} else {
				// Remove inline styles
				if (isIE) {
					flyoutMenu.style.removeAttribute("bottom", false);
					flyoutMenu.style.removeAttribute("position", false);
					flyoutMenu.style.removeAttribute("top", false);
				} else {
					flyoutMenu.style.bottom = "";
					flyoutMenu.style.position = "";
					flyoutMenu.style.top = "";
				}
			}
		}
	}
	/* ********************************************* */
}

MSFlyout.prototype.deactivate = function() {
	// Set Closing Timeout
	MSFlyout.closeTimeout[this.type] = setTimeout("MSFlyout.closeAll(\"" + this.type + "\")", MSFlyout.DEACTIVATION_TIMEOUT[this.type]);
}

MSFlyout.prototype.handleDeactivate = function() {
	// Deactivate MSFlyout
	if (this.type == MSFlyout.TYPE_METANAVLOGIN && !overMsNaviMeta && !hasInputFocus) {
		this.active = false;
		MSFlyout.popClassMN(this.flyout);
	}
	else{
		this.active = false;
		MSFlyout.popClass(this.flyout, MSFlyout.CSS_CLASS_HOVER);
	}
}
// Helper Methods
function getAbsTop(element) {
	if (element.offsetParent) {
		return element.offsetTop + getAbsTop(element.offsetParent);
	} else {
		return element.offsetTop;
	}
}

/**
 */
var /*HashMap*/ ms_corenav_elementsLoaded = new Object();
var /*HashMap*/ ms_corenav_elementsSelected = new Object();
var /*AJAXConnector*/ ajaxConnector = new AJAXConnector( );

function /*void*/ ms_corenav_handleRequest(status, data, param, type, statusmsg) {
	if(status == AJAXConnector.SUCCID_LOAD && type == AJAXConnector.RESPONSE_TEXT) {
		ms_corenav_printFlyout(param, data);
	}
}

function /*void*/ ms_corenav_loadFlyoutData(/*String*/ elementId, /*String*/ handle) {
	// Return, if no handle was given
	if (!handle || handle == "") {
		return;
	}
	
	// Process Ajax, if element has not been loaded yet
	if (ms_corenav_elementsLoaded[elementId] == undefined) {
		// Send Ajax request
		ajaxConnector.registerDataHandler(ms_corenav_handleRequest);
		ajaxConnector.setMaxRequestTime(10000);
		ajaxConnector.sendRequest(handle + ".ajax.component.corenavigation2.corenavigation2_Single.corenavigation2.html", "", AJAXConnector.REQUEST_GET, elementId);
	}
}

function /*void*/ ms_corenav_printFlyout(/*String*/ elementId, /*String*/ data) {
	// Print to Layer
	if (getLayer(elementId) != undefined) {
		// Replace elementId spacer
		data = data.replace(/{elementId}/g, elementId);
	
		// Paste response to layer
		getLayer(elementId).innerHTML = data;
		
		// Set counter for this elementId
		var /*int*/ counter = getLayer(elementId).getElementsByTagName("ul")[0].childNodes.length
		ms_corenav_elementsLoaded[elementId] = counter;

		// Init first list entry
		var /*List*/ links = getLayer(elementId).getElementsByTagName("li");
		if (links[0].firstChild) {
			ms_corenav_changeFlyout(links[0].firstChild, elementId, 0);
			ms_corenav_resetFlyout(links[0].firstChild, elementId, 0);
		}
	}
}

function ms_corenav_resetFlyout(/*XMLNode*/ callerObj, /*String*/ elementId, /*int*/ item) {
	// Get current marked node
	var /*XMLNode*/ current = ms_corenav_elementsSelected[elementId];
	
	// Reset the current class for IE
	if (document.all) {
		current.className = "ms-hover";
	}
}

function ms_corenav_changeFlyout(/*XMLNode*/ callerObj, /*String*/ elementId, /*int*/ item) {
	// Get current marked node
	var /*XMLNode*/ current = ms_corenav_elementsSelected[elementId];
	
	// IllegalArgumentException
	if (item < 0) {
		return;
	}

	// Check if current element has changed
	if (current == callerObj) {
		return;
	}

	// Reset previous marked element
	if (current != undefined) {
		if (current.className) {
			current.className = '';
		} else {
			current.removeAttribute("class");
		}
	}
	
	// Set current marked element
	if (callerObj.className) {
		callerObj.className = 'ms-hover';
	} else {
		callerObj.setAttribute("class", "ms-hover");
	}
	ms_corenav_elementsSelected[elementId] = callerObj;
	
	// Set all display:none
	for (var /*int*/ i = 0; i < ms_corenav_elementsLoaded[elementId]; i++) {
		getLayer(elementId + "-r" + i).style.display = "none";
		getLayer(elementId + "-b" + i).style.display = "none";
	}
	
	// Set specified number display:block
	getLayer(elementId + "-r" + item).style.display = "block";
	getLayer(elementId + "-b" + item).style.display = "block";
}

var /*Boolean*/ ms_setIFrameHeight_stopper = false;
function ms_setIFrameHeight(/*String*/flyoutId) {
	// Only IE6
	if (!window.attachEvent || window.opera || window.XMLHttpRequest) return;
	// Get IFrame and FlyOut element
	if (flyoutId == '') return;
	// Only CORE NAV Flyout Type 2
	
	var flyout = document.getElementById(flyoutId);
	var /*XMLNode*/ iframe = flyout.getElementsByTagName("IFRAME")[0];
	if (!iframe) return;
	var /*XMLNode*/ list = flyout.getElementsByTagName("UL")[0];
	if (!list) return;
			
	flyout.style.display = "";
	var /*int*/ height = list.offsetHeight;
	if (!ms_setIFrameHeight_stopper) {
		// Sometimes IE needs some time to render the hidden
		// elements, so we give it 25 additional milliseconds.
		ms_setIFrameHeight_stopper = true;
		setTimeout("ms_setIFrameHeight('" + flyoutId + "')", 25);
		return;
	} else if (ms_setIFrameHeight_stopper) {
		ms_setIFrameHeight_stopper = false;
	}
	
	// Set height on IFrame. In some cases the height of the iframe must be
	// larger than that of the list because the whole flyout is larger.
	if(iframe.parentNode.className == 'ms-navi-main-fly-v2-1'){
		iframe.style.height = (height + 18) + "px";
	}
	else if(iframe.parentNode.className == 'ms-navi-main-fly-v1-1'){
		iframe.style.height = 390 + "px";
	}
	else{
		iframe.style.height = height + "px";
	}
}

//functions for the CRM part of the MetaNav
function getCorrectMetaNav(salStructure){
	var userProfile = embGetProfileManager();
	
	var isLoggedIn = userProfile.isLoggedIn();
	if(isLoggedIn){
		var salutation = document.getElementById("cs-salutation").innerHTML;
		var greeting = buildGreetingString(salStructure);
		
		salutation = salutation + greeting;
		var elem;
		elem = document.getElementById("cs-salutation");
		if (elem) {
			elem.innerHTML = salutation;
		}
		
		elem = document.getElementById("loggedoutul");
		if (elem) {
			elem.style.display='none';
		}
		elem = document.getElementById("loggedinul");
		if (elem) {
			elem.style.display='block';
		}
	}
	else{
		var elem;
		elem = document.getElementById("loggedinul");
		if (elem) {
			elem.style.display='none';
		}
		elem = document.getElementById("loggedoutul");
		if (elem) {
			elem.style.display='block';
		}
	}
}

//get the correct form of the CoreNav3
function getCorrectNav3(showdf, showdmbp){
	var userProfile = embGetProfileManager();
	var isLoggedIn = userProfile.isLoggedIn();
	var hasFavoriteSet = userProfile.getFavoriteBmCode() && userProfile.getFavoriteBmCode().length > 0;
	var hasDealerSet = userProfile.getDealerName1() && userProfile.getDealerName1().length > 0;
	if(isLoggedIn){
		var dealer = userProfile.getDealerName1() + "<br>";
		dealer = dealer + userProfile.getDealerName2() + "<br>";
		dealer = dealer + userProfile.getDealerStreet() + "<br>";
		dealer = dealer + userProfile.getDealerZIP() + " ";
		dealer = dealer + userProfile.getDealerCity();
		var dynPicture = userProfile.getFavoriteImgSmallUrl();
		var dynFavorite = userProfile.getFavoriteName();
		document.getElementById("showifnotloggedin").style.display='none';
		if(showdf && hasFavoriteSet){
			var doomedElem = document.getElementById("crm-favorite-static");
			doomedElem.parentNode.removeChild(doomedElem);
			document.getElementById("loggedinpic").firstChild.removeAttribute("src");
			document.getElementById("loggedinpic").firstChild.setAttribute("src", dynPicture);
			document.getElementById("loggedinfav").innerHTML = dynFavorite;
		} else {
			var doomedElem = document.getElementById("crm-favorite-dynamic");
			doomedElem.parentNode.removeChild(doomedElem);
		}
		if(showdmbp && hasDealerSet){
			var doomedElem = document.getElementById("crm-mbpartner-static");
			doomedElem.parentNode.removeChild(doomedElem);
			document.getElementById("loggedindealer").innerHTML = dealer;
		} else {
			var doomedElem = document.getElementById("crm-mbpartner-dynamic");
			doomedElem.parentNode.removeChild(doomedElem);
		}
		document.getElementById("showifloggedin").style.display='block';
	}
	else{
		document.getElementById("showifloggedin").style.display='none';
		document.getElementById("showifnotloggedin").style.display='block';
	}
}

function buildGreetingString(greetingPattern) {
	
	var userProfile = embGetProfileManager();
	var greeting = greetingPattern.toString();
	
	greeting = greeting.replace(/%a/, userProfile.getSalutation());
	
	if (greeting.indexOf("%t") != -1) {
		var title = userProfile.getTitle();
		if (title && title.length > 0) {
			greeting = greeting.replace(/%t/, title);
		} else {
			greeting = greeting.replace(/ %t/, "");
		}
	}
	
	greeting = greeting.replace(/%f/, userProfile.getFirstName());
	
	if (greeting.indexOf("%m") != -1) {
		var secondFirstName = userProfile.getSecondFirstName();
		if (secondFirstName && secondFirstName.length > 0) {
			greeting = greeting.replace(/%m/, secondFirstName);
		} else {
			greeting = greeting.replace(/ %m/, "");
		}
	}
	
	greeting = greeting.replace(/%l/, userProfile.getLastName());
	
	if (greeting.indexOf("%s") != -1) {
		var secondLastName = userProfile.getSecondLastName();
		if (secondLastName && secondLastName.length > 0) {
			greeting = greeting.replace(/%s/, secondLastName);
		} else {
			greeting = greeting.replace(/ %s/, "");
		}
	}
	
	return greeting;
}

/**/
function AJAXConnector( )
{
	// public methods

	/**
	 * Sends a http request to server
	 * @param String, datasource on server, e.g. data.php
	 * @param String, query string to send to server, optionally
	 * @param int, request type, possible values: REQUEST_GET, REQUEST_POST, REQUEST_XML, REQUEST_HEAD default REQUEST_GET
	 * @param mix, param, e.g. array , will be handed over to registered callback function, optionally
	 * @param headers, request headers to be sent along with the request (as hash with key=header name and value=header value)
	 * @return Query string
	 * @type String
	 */
	this.sendRequest = function( strReqHandler, strQuery, intReqType, mixParam, headers )
		{
			if( !this._p_funcData )
			{
				if( this._p_handleData( ) )
					return;
			}

			if( !strQuery )
			{
				strQuery = '';
			}

			// default type (0 = GET, 1 = xml, 2 = POST )
			if( isNaN( intReqType ) )
			{
				intReqType = AJAXConnector.REQUEST_GET; // GET
			}

			// previous request not finished yet, abort it before sending a new request

			if( this._p_xmlHttp && this._p_xmlHttp.readyState )
			{
				this._p_stopMonitor(false);
				this._p_xmlHttp = false;
			}

			// create a new instance of xmlhttprequest object
			// if it fails, return
			if( !this._p_xmlHttp )
			{
				this._p_getReqObject( );
				if( !this._p_xmlHttp )
					return;
			}
			// parse query string
			if( strQuery.length && strQuery.substr( 0, 1 ) == '&' || strQuery.substr( 0, 1 ) == '?' )
				strQuery = strQuery.substring( 1, strQuery.length );
				
				
			this._p_isFile = false;
			var httpPattern = /http(s)?:\/\/.*/;
			var filePattern = /file:.*/;
			if (!httpPattern.test(strQuery)) {
				if (filePattern.test(window.location.href)) {
					this._p_isFile = true;
				}
			}
			
			// data to send using POST
			var dataReturn = strQuery ? strQuery : strReqHandler;
			switch( intReqType )
			{
				
				case AJAXConnector.REQUEST_POST: // POST
					// open the connection
					this._p_xmlHttp.open( "POST", strReqHandler, true );
					if (!headers && !headers["Content-Type"]) {
						this._p_xmlHttp.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
					}
					this._p_xmlHttp.setRequestHeader( 'Content-length', strQuery.length );
					break;
				case AJAXConnector.REQUEST_HEAD: // HEAD
					// open the connection
					this._p_xmlHttp.open( "HEAD", strReqHandler, true );
					strQuery = null;
					break;
				case AJAXConnector.REQUEST_GET: // GET
					// open the connection
					var strDataFile = strReqHandler + (strQuery ? '?' + strQuery : '' );
					this._p_xmlHttp.open( "GET", strDataFile, true );
					strQuery = null;
				default:
			}

			if (headers) {
				for (h in headers) {
					this._p_xmlHttp.setRequestHeader(h, headers[h]);
				}
			}

			this._p_param = null;
			if(mixParam) {
				this._p_param = mixParam;
			}

			// set onload data event-handler
			var me = this;
			this._p_xmlHttp.onreadystatechange = function() { me._p_processResponse() };


			// send request to server
			try
			{
				if( this._p_intTimeout )
					this._p_startMonitor( );
				this._p_xmlHttp.send( strQuery );	// param = POST data
			}
			catch( excSendError )
			{
				this._p_handleData( null, null, AJAXConnector.ERRID_SEND, ERR_SEND );
			}

			return dataReturn;
		};


	/**
	 * Given function to handle data from server
	 */
	this._p_funcData;

	/**
	 */
	this.registerDataHandler = function ( funcData ) {	this._p_funcData = funcData; };


	/**
	 * Given function to handle progress of the request
	 */
	this._p_funcProgress = null;

	/**
	 * Registers the progress handler function
	 * The data handler function is given two:<br />
	 * Param 1: current ready state (0 ... 4)<br />
	 * Param 2: the param data given as the "mix" parameter to sendRequest
	 * @param Function, Function to handle progress
	 */
	this.registerProgressHandler = function ( funcProgress ) {	this._p_funcProgress = funcProgress; };

	/**
	 * Max execution time for this request, 0 means infinite
	 */
	this._p_intTimeout				= 0;

	/**
	 * Sets max execution time for this request
	 * @param int, Time in milliseconds
	 */
	this.setMaxRequestTime			= function ( intTimeout ) { this._p_intTimeout = intTimeout; };


	// private methods

	/**
	 * An instance of the XMLHttpRequest object
	 */
	this._p_xmlHttp					= null;

	/**
	 * Instantiates a new xmlhttprequest object
	 * @return XMLHttpRequest-Object or false
	 * @type XMLHttpRequest | boolean
	 */
	this._p_getReqObject = function( )
		{

			// Mozilla, Opera und Safari
			try
			{
				this._p_xmlHttp = new XMLHttpRequest();
			}
			catch( excW3C )
			{
				// Internet Explorer
				for( var i = 5; i; i-- )
				{
					try
					{
						// loading of a newer version of msxml dll (msxml3 - msxml5) failed
						// use fallback solution
						// old style msxml version independent, deprecated
						if( i == 2 )
						{
							this._p_xmlHttp = new ActiveXObject( "Microsoft.XMLHTTP" );
						}
						// try to use the latest msxml dll
						else if( i > 2 )
						{
							this._p_xmlHttp = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
						}
						// loading of xmlhttp object failed
						else
						{
							this._p_handleError( null, null, AJAXConnector.ERRID_LOAD, ERR_LOAD );
						}
						break;
					}
					catch( excNotLoadable )	{}
				}
			}
		};


	/**
	 * Process the response data from server
	 * @param int, ID of this response
	 */
	this._p_processResponse = function( )
		{
			// status 0 UNINITIALIZED open() has not been called yet.
			// status 1 LOADING send() has not been called yet.
			// status 2 LOADED send() has been called, headers and status are available.
			// status 3 INTERACTIVE Downloading, responseText holds the partial data.
			// status 4 COMPLETED Finished with all operations.

			if (this._p_funcProgress) {
				try {
					this._p_funcProgress(this._p_xmlHttp.readyState, this._p_param);
				} catch (e) {
					// ignoring, code is for setting breakpoints in JS debugger.
					e = null;
				}
			}

			switch( this._p_xmlHttp.readyState )
			{
				// uninitialized
				case 0:
				// loading
				case 1:
				// loaded
				case 2:
				// interactive
				case 3:
					break;
				// complete
				case 4:
					// check http status
					
					var status = this._p_xmlHttp.status;
					var fileUrl = this._p_isFile;
					var success = !fileUrl && ((status == 200) || (status == 304));

					// status == 0 may be  success if a file: url is fetched
					if (status == 0) {
						success = (fileUrl && this._p_xmlHttp.responseText);
					}

					if(success)
					{
						// stop connection monitor
						this._p_stopMonitor(false, true);
						if( this._p_xmlHttp.responseXML && this._p_xmlHttp.responseXML.childNodes.length )
							this._p_handleData( this._p_xmlHttp.responseXML, AJAXConnector.RESPONSE_XML, AJAXConnector.SUCCID_LOAD, SUCC_LOAD );
						else {
							this._p_handleData( this._p_xmlHttp.responseText, AJAXConnector.RESPONSE_TEXT, AJAXConnector.SUCCID_LOAD, SUCC_LOAD );
						}
					}
					// loading not successfull, e.g. page not available
					else
					{
						if( !this._p_xmlHttp.status )
							this._p_handleData( null, null, AJAXConnector.ERRID_SEND, ERR_SEND );
						else
							this._p_handleData( null, null, this._p_xmlHttp.status, this._p_xmlHttp.statusText );
					}
			}
		};


	/**
	 * Shows an error message or calls a given error handler
	 * @param String, data from server as xml or plain text
	 * @param String, constant for xml or plain text (AJAXConnector.RESPONSE_XML | AJAXConnector.RESPONSE_TEXT)
	 * @param int, id of current request
	 * @param mix, param set by method 'registerUserParam'
	 * @param int, error id or http status
	 * @param String, error message or http status message
	 */
	this._p_handleData = function( objResponseData, intType, intStatusID, strStatusMsg )
		{
			if( this._p_funcData )
			{
				this._p_funcData( intStatusID, objResponseData, this._p_param, intType, strStatusMsg );
			}
			else
			{
				alert( "Error-ID: " + AJAXConnector.ERRID_NOHANDLER + "\nError-Message: " + ERR_NOHANDLER );
			}
		};

	/**
	 * Starts the timeout monitor
	 */
	this._p_startMonitor = function () 
	{ 
		var me = this;
		this._p_to = setTimeout( function() {me._p_stopMonitor( true )}, this._p_intTimeout ); 
		
	};

	/**
	 * Stops the timeout monitor
	 */
	this._p_stopMonitor = function( blnIsTimeout, blnStopTimer )
		{
			if(!blnStopTimer) {
				this._p_xmlHttp.onreadystatechange = function () {}
				this._p_xmlHttp.abort( );
			}

			if( blnIsTimeout && this._p_xmlHttp && this._p_xmlHttp.readyState)
			{
				this._p_handleData( null, null, AJAXConnector.ERRID_TIMEOUT, ERR_TIMEOUT );
			}
			else if(this._p_to)
			{
				clearTimeout( this._p_to );
				this._p_to = null;
			}
		};



	// status messages and id's
	var SUCC_LOAD					= "Fetching of data successfully finished";
	var ERR_LOAD					= "Unable to instantiate XMLRequestObject";
	var ERR_NOHANDLER				= "No Data-Handler registered";
	var ERR_SEND					= "Unable to send data. Is your Computer connected to the internet?";
	var ERR_TIMEOUT					= "Operation timed out.";
}


// Constants

/**
 * Constant indicates that data may be send using the get method
 * @type int
 * @final
 */
AJAXConnector.REQUEST_GET	= 0;

/**
 * Constant indicates that data may be send using the post method
 * @type int
 * @final
 */
AJAXConnector.REQUEST_POST	= 2;

/**
 * Constant indicates that data may be send using the post method
 * this may be used to get only the modified date of a file
 * @type int
 * @final
 */
AJAXConnector.REQUEST_HEAD	= 1;


/**
 * Constant indicates that response type is xml
 * @type int
 * @final
 */
AJAXConnector.RESPONSE_XML	= 1;

/**
 * Constant indicates that response type is text
 * @type int
 * @final
 */
AJAXConnector.RESPONSE_TEXT	= 2;


/**
 * Request successfully finished
 * @type int
 * @final
 */
AJAXConnector.SUCCID_LOAD					= 0;

/**
 * XMLRequestObject could not be instantiated
 * @type int
 * @final
 */
AJAXConnector.ERRID_LOAD					= 1;

/**
 * No data handler registered
 * @type int
 * @final
 */
AJAXConnector.ERRID_NOHANDLER				= 2;

/**
 * Data could not be sent to server
 * @type int
 * @final
 */
AJAXConnector.ERRID_SEND					= 3;

/**
 * Request last too long
 * @type int
 * @final
 */
AJAXConnector.ERRID_TIMEOUT				= 4;

