﻿
/*  pro aurum featureDisplay Library, version 1.1 - 01.12.2009 - 14:26
 *  (c) 2009 SiteForce - Florian Kirchberger
 *
 *----------------------------------------------*/
 
 // #### AJAX XML HTTP REQUEST CONSTANTS  #####
var xmlHttp = false;  				// ### AJAX global xmlhttprequest object
var REQUEST_GET = 0;
var REQUEST_POST = 2;
var REQUEST_HEAD = 1;
var REQUEST_XML = 3;
var gSERVERSYNCTIME = 4000;
var gCOUNTDOWNDIGITS = 6;
var gMaxDigits = gCOUNTDOWNDIGITS;
var gAJAXERRORCOUNTER = 0;
var requestAjaxDataCount = 0;

var gCountDownValue = null;
var gDecrementDelay = null;
var gAjaxIntervalHandel = null;
var gDecrementHandel = null;

var gCountDownObjectArray = new Array(); // ## global array of all countdown objects
var gCountDownObjectCounter = 0; // ## global counter of countdown objects

var gShopSpecialTickerObject = null; // ## global gShopSpecialTickerObject
var gShopSpecialTickerDisplayId = "shopSpecialTickerDisplay"; // ## DOM element id of used featureDisplay

//alert("gFeatureDisplayAjaxURL: " + gFeatureDisplayAjaxURL);

var map = null; /// ### google Map Object
var gdir; /// ### routenplaner
var geocoder = null;
var addressMarker;


var gZoomLevel = 15; /// ### google map default zoom level

// #######################   initScreen  ###########################
function initFeatureDisplay() {
	ajaxCountdownRequest();
	gAjaxIntervalHandel = window.setInterval("ajaxCountdownRequest()",gSERVERSYNCTIME);
}


// #######################   ajaxCountdownRequest  ###########################
function ajaxCountdownRequest() {
	var requestURL = gFeatureDisplayAjaxURL;	
	var requestQuery = "";
	var requestType = 1; // ## 0 = GET, 1 = XML, 2 = POST
	requestAjaxDataCount ++; // ## requestIdCount of this request, will be given to registered event handler onreadystatechange
		
	sendAJAXRequest(requestURL , requestQuery , requestType, requestAjaxDataCount);	
}


//#########   initMap   ########
function initMap(longitude,latitude,addressStreet, addressZip, addressCity, addressCountryCode) {
       	
    	var mapDIVElement = document.getElementById("map");
    	if(mapDIVElement != null){
      		if (GBrowserIsCompatible()) {
      			map = new GMap2(mapDIVElement);

        	 	// ### pin overlay  ###
      			map.setCenter(new GLatLng(latitude, longitude), gZoomLevel);
        	    	
        		// ### pin overlay  ###
        		var latlng = new GLatLng(latitude,longitude);
          		map.addOverlay(new GMarker(latlng));
          						
				//getUserGEOLocation();
      		
      		 	var customUI = map.getDefaultUI();
        		customUI.maptypes.hybrid = false; // Remove MapType.G_HYBRID_MAP
        		customUI.maptypes.satellite = false; // Remove MapType.G_SATELLITE_MAP
        		customUI.maptypes.physical = false; // Remove MapType.G_PHYSICAL_MAP 
        		map.setUI(customUI);


				// ### routenplaner  ###
				gdir = new GDirections(map, document.getElementById("directions"));
				GEvent.addListener(gdir, "load", onGDirectionsLoad);
				GEvent.addListener(gdir, "error", handleErrors);
				
				var toAddressElement = document.getElementById("toAddress");
				if(toAddressElement != null){
					var adressString = addressZip + ", " + addressStreet + ", " + addressCountryCode;
					toAddressElement.value = adressString;
				}
    
			}	
        }
  
      	
    }
    

// #######################   setDirections  ###########################
function setDirections(fromAddress, toAddress) {
	var locale = "de";   
	gdir.load("from: " + fromAddress + " to: " + toAddress, { "locale": locale });
	
}

// #######################   handleErrors  ###########################
function handleErrors(){
	   if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
	    	alert("Die eingegebene Startadresse wurde nicht gefunden!\n\nEventuell ist die Startadresse unvollständig, fehlerhaft oder zu neu.\n\nEingabeformat: Straße Hausnummer, Postleitzahl Ort");
	   else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
	   		alert("Leider konnte die Route nicht berechnet werden!\n\nDie genaue Ursache ist leider unbekannt.");
	   
	   else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
	     alert("Es wurden keine Parameter für die Suche übergeben.");
	     
	   else if (gdir.getStatus().code == G_GEO_BAD_KEY)
	     alert("Der Google Maps-API-Schlüssel ist entweder ungültig oder für eine andere Website registriert worden. \n Fehler: " + gdir.getStatus().code);

	   else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
	     alert("Leider konnte die Route nicht berechnet werden.\n\nFehler: " + gdir.getStatus().code);
	    
	   else alert("Unbekannter Fehler!");
	   
}


// #######################   onGDirectionsLoad  ###########################
function onGDirectionsLoad(){ 
      // Use this function to access information about the latest load()
      // results.

      // e.g.
      // document.getElementById("getStatus").innerHTML = gdir.getStatus().code;
	  // and yada yada yada...
}


// #######################   displayData  ###########################
function displayData(data) {
	gCountDownObjectArray = new Array(); // ## global array of all countdown objects
	gCountDownObjectCounter = 0; // ## global counter of countdown objects

	//#####   parse XML DATA  #####
	var entryArray = data.getElementsByTagName('entry');	
	if(entryArray == null) return;
	
	if(entryArray.length > 0){
		for(var n = 0; n < entryArray.length; n++){
			entry = entryArray[n];
			
			var askPriceWithTax = getXMLTagValue(entry,'askPriceWithTax');			
			var priceAdjustment = 1.0 * getXMLTagValue(entry,'priceAdjustment');
			var priceAdjustmentFormatted = formatZahl(priceAdjustment, 2, true);
		
			countDownObject = {
				initialCounter: 		getXMLTagValue(entry,'initialCounter'),
				actualCounter:  		getXMLTagValue(entry,'actualCounter'),
				actualSpeed:   			getXMLTagValue(entry,'actualSpeed'),
				shopId:   				getXMLTagValue(entry,'shopId'),
				shopSpecialId:			getXMLTagValue(entry,'shopSpecialId'),
				status:   				getXMLTagValue(entry,'status'),
				featureDisplayImage1:   getXMLTagValue(entry,'featureDisplayImage1'),
				featureDisplayImage2:   getXMLTagValue(entry,'featureDisplayImage2'),
				featureDisplayImage3:   getXMLTagValue(entry,'featureDisplayImage3'),
				productImage:   		getXMLTagValue(entry,'productImage'),
				askPriceWithTax:		getXMLTagValue(entry,'askPriceWithTax'),
				vatRate:				getXMLTagValue(entry,'vatRate'),
				priceAdjustment:		priceAdjustmentFormatted,
				isAdjustmentPercentage:	getXMLTagValue(entry,'isAdjustmentPercentage'),
				currency:				getXMLTagValue(entry,'currency'),
				productName:			getXMLTagValue(entry,'productName')
			};
			
			gCountDownObjectArray[gCountDownObjectCounter] = countDownObject;	
			gCountDownObjectCounter ++;
		}
	
		if(gCountDownObjectArray.length >= 0){
			gShopSpecialTickerObject = gCountDownObjectArray[0]; // ### select first element of array
			if(gShopSpecialTickerObject != null){
				gAJAXERRORCOUNTER = 0; // ## reset ajax error counter if a data object has been sucessfully received
				//alert(gShopSpecialTickerObject.actualCounter);
				var initialCounterStr = "" + gShopSpecialTickerObject.initialCounter;
				gMaxDigits = initialCounterStr.length;
				if(gMaxDigits > gCOUNTDOWNDIGITS){gMaxDigits = gCOUNTDOWNDIGITS;}
				if(gCountDownValue == null){
					gCountDownValue = gShopSpecialTickerObject.actualCounter;
				}
				
				updateFeatureDisplay(gShopSpecialTickerDisplayId, gShopSpecialTickerObject);
			}
		} else {
			gShopSpecialTickerObject = null;
		}
	}
}


// #######################   clickFeatureDisplay  ###########################
function clickFeatureDisplay(clickObject) {	
	//alert("shopSpecialId: " + gShopSpecialTickerObject.shopSpecialId);
	if(gFeatureDetailsUrl != null){
		if(gFeatureDetailsUrl.length > 1 ){
			document.location.href = gFeatureDetailsUrl;
		}
	}	
}


// #######################   updateFeatureDisplay  ###########################
function updateFeatureDisplay(id, displayDataObject) {
	
	var initialCounter = displayDataObject.initialCounter;
	var actualCounter = displayDataObject.actualCounter;
	var actualSpeed = displayDataObject.actualSpeed;
	var status = displayDataObject.status;
	
		
	updateHeaderBgndImage(displayDataObject.productImage); // ## uodate shopw special header bgnd
	
	setInnerHtml('vatRate', displayDataObject.vatRate);
	
	// ############ percentage price adjustment ############
	if(displayDataObject.isAdjustmentPercentage == "true"){
		updatePriceAdjustment(displayDataObject.priceAdjustment, "%");
	} else {
		updatePriceAdjustment(displayDataObject.priceAdjustment, displayDataObject.currency);
	}		
	
	if(status == "BEFORE_START"){
		updateFeatureDisplayBgndImage(id, displayDataObject.featureDisplayImage1); // ## pre phase image
		updateCountdownDisplay(initialCounter,initialCounter,0);
		updatePrice(displayDataObject.askPriceWithTax, displayDataObject.currency);
		displayElement(id, true);
		displayElement("featureDisplayPriceVatCountdownArea", false);
		displayElement('priceDigitArea', false);
		displayElement('countDownArea', false);
		displayElement('vatArea', false);
		displayElement('countDownLabel', false);
		displayElement('displayBEFORE', true);
		displayElement('displayDONE', false);
	}
	
	if(status == "RUNNING"){
		updateFeatureDisplayBgndImage(id, displayDataObject.featureDisplayImage2); // ## normal phase image
		updateCountdownDisplay(initialCounter,actualCounter,actualSpeed);
		updatePrice(displayDataObject.askPriceWithTax, displayDataObject.currency);
		displayElement(id, true);
		displayElement("featureDisplayPriceVatCountdownArea", true);
		displayElement('countDownArea', true);
		displayElement('priceDigitArea', true);
		displayElement('vatArea', true);
		displayElement('countDownLabel', true);
		displayElement('displayBEFORE', false);
		displayElement('displayDONE', false);
	}
	
	if(status == "WAITING"){
		updateFeatureDisplayBgndImage(id, displayDataObject.featureDisplayImage2); // ## normal phase image
		updateCountdownDisplay(initialCounter,actualCounter,0);
		updatePrice(displayDataObject.askPriceWithTax, displayDataObject.currency);
		displayElement(id, true);
		displayElement("featureDisplayPriceVatCountdownArea", true);
		displayElement('countDownArea', true);
		displayElement('priceDigitArea', true);
		displayElement('vatArea', true);
		displayElement('countDownLabel', true);
		displayElement('displayBEFORE', false);
		displayElement('displayDONE', false);
	}
	
	if(status == "DONE"){
		updateFeatureDisplayBgndImage(id, displayDataObject.featureDisplayImage3); // ## finished phase image
		updateCountdownDisplay(0,0,0);
		displayElement(id, true);
		displayElement("featureDisplayPriceVatCountdownArea", true);
		displayElement('countDownArea', true);
		displayElement('priceDigitArea', false);
		displayElement('vatArea', false);
		displayElement('countDownLabel', true);
		displayElement('displayBEFORE', false);
		displayElement('displayDONE', true);
	}
	
	if(status == "INACTIVE"){
		displayElement(id, false);
		updateFeatureDisplayBgndImage(id, displayDataObject.featureDisplayImage1);
		updateCountdownDisplay(0,0,0);
		displayElement("featureDisplayPriceVatCountdownArea", false);
		displayElement('priceDigitArea', false);
		displayElement('vatArea', false);
		displayElement('countDownArea', false);
		displayElement('countDownLabel', false);
		displayElement('displayBEFORE', false);
		displayElement('displayDONE', false);
	}
	
	
}

// #######################   updateFeatureDisplayBgndImage  ###########################
function updateFeatureDisplayBgndImage(id, imagePath) {
	if(imagePath != null && id != null){
		if(imagePath.length > 1){
			var imageUrl = imagePath;
			var featureDisplayElement = document.getElementById(id); // ### get the featureDisplayElement Element
			if(featureDisplayElement != null){
				var actualBgndImage = featureDisplayElement.style.backgroundImage;
				if(actualBgndImage.indexOf(imagePath) == -1){
					featureDisplayElement.style.backgroundImage =  'url(' + imageUrl + ')';
				}
			}
			
		}
	}
}


// #######################   updateHeaderBgndImage  ###########################
function updateHeaderBgndImage(imagePath) {

	var id = "shopSpecialHeaderArea";
	if(imagePath != null && id != null){
		if(imagePath.length > 1){
			var imageUrl = imagePath;
			var headerElement = document.getElementById(id); // ### get the featureDisplayElement Element
			if(headerElement != null){
				var actualBgndImage = headerElement.style.backgroundImage;
				if(actualBgndImage.indexOf(imagePath) == -1){
					
					headerElement.style.backgroundImage =  'url(' + imageUrl + ')';
				}
			}
			
		}
	}
}


// #######################   updateCountdown  ###########################
function updateCountdownDisplay(initialCounter,actualCounter,actualSpeed) {
	
	if(actualSpeed > 0){
		if(actualCounter > gCountDownValue){
			window.clearInterval(gDecrementHandel);
			return;
		}
		
		gDecrementDelay = Math.round(700.0 / (actualSpeed / 60.0 / 60.0));
		var targetValue = actualCounter;
		if(gDecrementDelay > 4000){
			showCountdownDisplayValue(gCountDownValue);
		}
		//alert("gCountDownValue: " + gCountDownValue + "\ntargetValue: " + targetValue + "\nactualSpeed: " + actualSpeed + "\ngDecrementDelay: " + gDecrementDelay);
		
		window.clearInterval(gDecrementHandel);
		gDecrementHandel = window.setInterval("decrementCountdownDisplay(" + targetValue +")", gDecrementDelay);
	} else {
		gCountDownValue = actualCounter;
		window.clearInterval(gDecrementHandel);
		showCountdownDisplayValue(gCountDownValue);
	}

}


// #######################   decrementCountdownDisplay  ###########################
function decrementCountdownDisplay(targetValue) {
	
	if(typeof(targetValue) == "undefined") {
		return;
	}
		
	if(gCountDownValue <= targetValue) {
		gCountDownValue = targetValue;
		window.clearInterval(gDecrementHandel);
	}
	
	if(gCountDownValue < 0) {
		gCountDownValue = 0;
		window.clearInterval(gDecrementHandel);
	}
		
	showCountdownDisplayValue(gCountDownValue);
	
	gCountDownValue --;
	
}


// #######################   showCountdownDisplayValue  ###########################
function showCountdownDisplayValue(mValue) {
		
	displayElement('countDownArea', true);
		
	var valueString = "" + mValue;
	var valueLength = valueString.length;
	
	// ## update Digits ##
	for(var digit = 1; digit <= gCOUNTDOWNDIGITS; digit++){
		var digitElementId = "countdownDigit_" + digit;
		
		if(digit <= valueLength && digit <= gMaxDigits){
			var character = valueString.substr(valueLength - digit, 1);
	 		var characterValue = parseInt(character);	
	 		setDigit(digitElementId, characterValue);
	 	} else {
	 		var characterValue = 0;
	 		setDigit(digitElementId, characterValue);
	 	}
	}
	
	
	// ## only display needed countdown digits  ##
	for(var i = 1; i <= gCOUNTDOWNDIGITS; i++){
		var digitElementID = "countdownDigit_" + i;
		if(i <= gMaxDigits){
			displayElement(digitElementID, true);
		} else {
			displayElement(digitElementID, false);
		}
	}
	
}



// #######################   updatePrice  ###########################
function updatePrice(value, currency) {

	var objectArray = new Array("priceDigit_12","priceDigit_11","priceDigit_10","priceDigit_9","priceDigit_8", "priceDigit_7", "priceDigit_6", "priceDigit_5", "priceDigit_4", "priceDigit_3", "priceDigit_2", "priceDigit_1");	
	
	var valueString = "" + value;
	var valueLength = valueString.length;
	
	//alert("valueString: " + valueString + " valueLength: " + valueLength);
	var kerning = 0;
	
	var charCounter = 0;
	for(var i = 0; i < objectArray.length; i++){
		var object = objectArray[i];
		var id = object;
	
		if(charCounter >= 0 && charCounter <= valueLength){
	 		var character = valueString.substr(charCounter, 1);
			setFontChar(id, character, kerning);
	 		charCounter ++;	
		}
		
		// #### currency  ####
		if(i == valueLength){
			setFontChar(id, currency, kerning);
		}
	}	
}

// #######################   updatePriceAdjustment  ###########################
function updatePriceAdjustment(value, unit) {

	var objectArray = new Array("priceAdjustDigit_12","priceAdjustDigit_11","priceAdjustDigit_10","priceAdjustDigit_9","priceAdjustDigit_8", "priceAdjustDigit_7", "priceAdjustDigit_6", "priceAdjustDigit_5", "priceAdjustDigit_4", "priceAdjustDigit_3", "priceAdjustDigit_2", "priceAdjustDigit_1");	
	
	var valueString = "" + value;
	var valueLength = valueString.length;
	
	//alert("valueString: " + valueString + " valueLength: " + valueLength);
	var kerning = -2;
	var charCounter = 0;
	for(var i = 0; i < objectArray.length; i++){
		var object = objectArray[i];
		var id = object;
	
		if(charCounter >= 0 && charCounter <= valueLength){
	 		var character = valueString.substr(charCounter, 1);
			setFontChar(id, character, kerning);
	 		charCounter ++;	
		}
		
		// #### unit  ####
		if(i == valueLength){
			setFontChar(id, unit, kerning);
		}
	}	
}



// #######################   setFontChar  ###########################
function setFontChar(id, character, kerning) {

	var fontArray = new Array();
	fontArray["0"] = {y:0, width:15};
	fontArray["1"] = {y:30, width:13};
	fontArray["2"] = {y:60, width:15};
	fontArray["3"] = {y:90, width:15};
	fontArray["4"] = {y:120, width:15};
	fontArray["5"] = {y:150, width:15};
	fontArray["6"] = {y:180, width:15};
	fontArray["7"] = {y:210, width:15};
	fontArray["8"] = {y:240, width:15};
	fontArray["9"] = {y:270, width:15};
	fontArray[" "] = {y:300, width:10};
	fontArray[","] = {y:330, width:8};
	fontArray["."] = {y:360, width:8};
	fontArray["-"] = {y:390, width:12};
	fontArray["+"] = {y:420, width:18};
	fontArray["*"] = {y:450, width:15};
	fontArray["%"] = {y:480, width:24};
	fontArray["EUR"] = {y:510, width:59};
	fontArray["USD"] = {y:540, width:59};
	fontArray["CHF"] = {y:570, width:59};
		
	var fontData = fontArray[character];
	if(fontData != null){
		var digitElement = document.getElementById(id); // ### get the digitElement Element
	 	if(digitElement != null){
	 		digitElement.style.backgroundPosition = "0px -" + fontData.y + "px";
	 		digitElement.style.width = (fontData.width + kerning ) + "px";
	 	} 			
	}
}


// #######################   setDigit  ###########################
function setDigit(id, value) {
	
	var digitHeight = 52;
	var stepMax = 4;
	var digitElement = document.getElementById(id); // ### get the digitElement Element		
	if(digitElement == null){return;}
	
	if(value != null){
		var offsetY = parseInt(value) * digitHeight * stepMax; //65;		
		digitElement.style.backgroundPosition = "0px -" + offsetY + "px";	
	} else {
		var offsetY = 2860;
		digitElement.style.backgroundPosition = "0px -" + offsetY + "px";
	}
		
}

// ############  Zahlen formatieren  ###########
// usage: format_zahl( number [, number]  [, bool]  )
function formatZahl(zahl, k, fix) {
    if(!k) k = 0;
    var neu = '';
    // Runden
    var f = Math.pow(10, k);
    zahl = '' + parseInt( zahl * f + (.5 * (zahl > 0 ? 1 : -1)) ) / f ;

    // Komma ermittlen
    var idx = zahl.indexOf('.');

    // fehlende Nullen einf?gen
    if(fix) {
         zahl += (idx == -1 ? '.' : '' )
         + f.toString().substring(1);
    }

    // Nachkommastellen ermittlen
    idx = zahl.indexOf('.');
    if( idx == -1) idx = zahl.length;
    else neu = ',' + zahl.substr(idx + 1, k);

    // Tausendertrennzeichen
    while(idx > 0)    {
        if(idx - 3 > 0)
        neu = '.' + zahl.substring( idx - 3, idx) + neu;
        else
        neu = zahl.substring(0, idx) + neu;
        idx -= 3;
    }

    return neu;
}


// ###########   attachEventListener #############
function attachEventListener(target, eventType, functionRef, capture){
		// ## cross browser compatible attachEventListener function -- function can be called with a pointer or a string representing a function name
	
      	if (typeof(functionRef)== 'string') {
            functionRef=eval(functionRef);
      	}

  		if (typeof target.addEventListener != "undefined"){
    		target.addEventListener(eventType, functionRef, capture);
		} else if (typeof target.attachEvent != "undefined"){
			target.attachEvent("on" + eventType, functionRef);
  		} else {
    		eventType = "on" + eventType;
		
    	if(typeof target[eventType] == "function"){
        	var oldListener = target[eventType];
        	target[eventType] = function(){
            	oldListener();
            	return functionRef();
        	};

    	} else {
        	target[eventType] = functionRef;
    	}

  	}

}


//#########  ShowObjectProperties  #############
function ShowObjectProperties(mObject) {
	var mWindow = window.open("", "DEBUG", "toolbar=0,location=0,directories=0,scrollbars=1,status=0,menubar=1,resizable=1,width=500,height=600");
	mWindow.document.open();

	for (var i in mObject) {
		mWindow.document.write('<BR><B>' + i + '</B> = ' + mObject[i] );
	}

	mWindow.document.close();
	mWindow.focus();
}


// ###########  getXMLTagValue  ###########
function getXMLTagValue(mDomObject, mTagName ){
	var mReturnValue = ""; 
	if(mDomObject != null) {
		// mDomObject.getElementsByTagName('title').item(0).firstChild.nodeValue ;
		var mChildList = mDomObject.getElementsByTagName(mTagName);
		if(mChildList.length > 0){
			if(mChildList[0].firstChild != null){
				var mFirstChildNodeValue = mChildList[0].firstChild.nodeValue;
			}
			if(mFirstChildNodeValue != null){ mReturnValue = mFirstChildNodeValue; }		
		}
	}
	return mReturnValue;
}


// ###########  getXMLTagAttribute  ###########
function getXMLTagAttribute(mDomObject, mTagName, mAttributeName ){
	var returnValue = ""; 
	if(mDomObject != null) {
		var mChildList = mDomObject.getElementsByTagName(mTagName);
		if(mChildList.length > 0){
			if(mChildList[0] != null){
				//ShowObjectProperties(mChildList[0]);
				var attributeValue = mChildList[0].getAttribute(mAttributeName);;
			}
			if(attributeValue != null){ returnValue = attributeValue; }		
		}
	}

	return returnValue;
}


// ### setInnerHtml  ###
function setInnerHtml(elementId, innerHtmlText) {
	var element = document.getElementById(elementId);
	if(element != null) {
		element.innerHTML = "" + innerHtmlText;
	}
}

// ###############   displayElement    ###############
function displayElement(id, status){
	if(status == null){var status = true;}
	
	var element = document.getElementById(id);
	if(element != null) {
		if(status == false){
			element.style.display = "none";
			element.style.visibility = "hidden";
		}
		
		if(status == true){
			element.style.display = "block";
			element.style.visibility = "visible";
		}
	}
}

// ###################################################################################
// ####################################  AJAX Handler ################################
// ###################################################################################
 
 
 // ###########  processAJAXData  ###########
function processAJAXData(xmlHttp, intID ){
    //var data = xmlHttp.responseText; // ## used for pure text 
    var data = xmlHttp.responseXML;  // ## used for XML 
   
   //alert("processAJAXData " + data);
	if(data == null){return;} // ## start XML parsing onyl if responseXML data is existing
	displayData(data); // ### call generic displayData Handler   
}


// #############  getXMLRequester  - returns xmlhttprequest object or false  ##########
function getXMLRequester( ) {
    var xmlHttp = false;
            
    // try to create a new instance of the xmlhttprequest object        
    try {
        // Internet Explorer
        if( window.ActiveXObject ){
            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 ){
                        xmlHttp = new ActiveXObject( "Microsoft.XMLHTTP" );    
                    }
                    // try to use the latest msxml dll
                    else {
                        xmlHttp = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
                    }
                    break;
                }
                catch( excNotLoadable ) {                        
                    xmlHttp = false;
                }
            }
        }
        // Mozilla, Opera und Safari
        else if( window.XMLHttpRequest )
        {
            xmlHttp = new XMLHttpRequest();
        }
    }
    // loading of xmlhttp object failed
    catch( excNotLoadable ){
        xmlHttp = false;
    }
    
    return xmlHttp ;
}

 
// ##########  sendAJAXRequest  #########
function sendAJAXRequest( strSource, strData, intType, intID ) {
    if( !strData )
        strData = '';

    // default type (0 = GET, 1 = xml, 2 = POST )
    if( isNaN( intType ) )
        intType = 0; // GET

    // previous request not finished yet, abort it before sending a new request
    if( xmlHttp && xmlHttp.readyState )
    {
        xmlHttp.abort( );
        xmlHttp = false;
    }
        
    // create a new instance of xmlhttprequest object
    // if it fails, return
    if( !xmlHttp )
    {
        xmlHttp = getXMLRequester( );
        if( !xmlHttp )
            return;
    }
    
    // parse query string
    if( intType != 1 && ( strData && strData.substr( 0, 1 ) == '&' || strData.substr( 0, 1 ) == '?' ) )
        strData = strData.substring( 1, strData.length );

    // data to send using POST
    var dataReturn = strData ? strData : strSource;
    
    switch( intType ) {
        case 1:    // xml
            strData = "xml=" + strData;
        case 2: // POST
            // open the connection 
            xmlHttp.open( "POST", strSource, true );
            xmlHttp.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
            xmlHttp.setRequestHeader( 'Content-length', strData.length );
            break;
        case 3: // HEAD
            // open the connection 
            xmlHttp.open( "HEAD", strSource, true );
            strData = null;
            break;
        default: // GET
            // open the connection 
            var strDataFile = strSource + (strData ? '?' + strData : '' );
            xmlHttp.open( "GET", strDataFile, true );
            strData = null;
    }
    
    // set onload data event-handler
    xmlHttp.onreadystatechange = new Function( "", "processAJAXResponse(" + intID + ")" ); ;

    // send request to server
    xmlHttp.send( strData );    // param = POST data
    
    return dataReturn;
}



// ##########  handleAJAXError - handle response errors   ###########
function handleAJAXError( xmlHttp, intID ){
	
	gAJAXERRORCOUNTER ++;
	if(gAJAXERRORCOUNTER >= 2){
		// ##### hide gShopSpecialTickerDisplayId if AJAX error occured #####
		if(gShopSpecialTickerDisplayId != null){
			displayElement(gShopSpecialTickerDisplayId, false);
		}
	}
}


 // ################  processAJAXResponse  #################
function processAJAXResponse( intID ) {
    // 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.
    switch( xmlHttp.readyState ) {
        // uninitialized
        case 0:
        // loading
        case 1:
        // loaded
        case 2:
        // interactive
        case 3:
            break;
        // complete
        case 4:    
            // check http status
            if( xmlHttp.status == 200 )    // success
            {
                processAJAXData( xmlHttp, intID );
            }
            // loading not successfull, e.g. page not available
            else
            {
                if( window.handleAJAXError )
                    handleAJAXError( xmlHttp, intID );
                else
                    alert( "ERROR\n HTTP status = " + xmlHttp.status + "\n" + xmlHttp.statusText ) ;
            }
    }
}

