function NonCacheableDataRequest(URL)
{
	var newStr;
	this.url = URL;
	this.priceProductRefs = new Object();
	this.leadtimeProductRefs = new Object();
	this.xmlHttpObj = new XMLHttpRequest();
	this.observers = new Array();
	
	this.registerObserver = function(oberserver, extThis)
	{
		var wrapped_callback = new ContextFixer(oberserver, extThis, this.xmlHttpObj);
		this.observers.push(wrapped_callback);
	}

	this.determineData = function()
	{
		this.collectPriceProductRefs();
		this.collectLeadtimeProductRefs();
		if (this.xmlHttpObj)
		{
			var requestStr = "";
			
			for (var pr in this.priceProductRefs)
			{
				newStr = new String(pr.replace("+","%2b"));
				requestStr = requestStr + ("&price-pref=" + newStr);
			}
			
			for (var lt in this.leadtimeProductRefs)
			{
				newStr = new String(lt.replace("+","%2b"));
				requestStr = requestStr + ("&leadtime-pref=" + newStr);
			}
			requestStr = requestStr + "&";
			
			if (requestStr.length <= 0)
			{
				return;
			}

			this.xmlHttpObj.open("POST", this.url,  true);
			this.xmlHttpObj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			
			var wrapped_callback = new ContextFixer(this.handleUpdate, this);
			this.xmlHttpObj.onreadystatechange = wrapped_callback.execute;
			
			this.xmlHttpObj.send(requestStr);
		}
	}

	this.collectPriceProductRefs = function()
	{
		var i = 1;
		var outerDivTagPrefix = "price-productref-";
		
		var myDiv = document.getElementById(outerDivTagPrefix + i);
		
		while (myDiv != null)
		{
			var productRef = myDiv.getElementsByTagName("div")[0].getAttribute("id")
			this.addToPriceProductRefs(productRef, outerDivTagPrefix + i);
			myDiv = document.getElementById(outerDivTagPrefix + (++i));
		}
		
		this.registerObserver(this.handlePriceUpdate, this); 
	}

	this.collectLeadtimeProductRefs = function()
	{
		var i = 1;
		var outerSpanTagPrefix = "leadtime-productref-";
		
		var mySpan = document.getElementById(outerSpanTagPrefix + i);
		
		while (mySpan != null)
		{
			var productRef = mySpan.getElementsByTagName("span")[0].getAttribute("id")
			this.addToLeadtimeProductRefs(productRef, outerSpanTagPrefix + i);
			mySpan = document.getElementById(outerSpanTagPrefix + (++i));
		}
		
		this.registerObserver(this.handleLeadtimeUpdate, this);
	}
	
	this.addToPriceProductRefs = function(productRef, divTagId)
	{
		if (!this.priceProductRefs[productRef])
		{
			this.priceProductRefs[productRef] = new Array();
		}
		this.priceProductRefs[productRef].push(divTagId);
	}
	
	
	this.addToLeadtimeProductRefs = function(productRef, divTagId)
	{
		if (!this.leadtimeProductRefs[productRef])
		{
			this.leadtimeProductRefs[productRef] = new Array();
		}
		this.leadtimeProductRefs[productRef].push(divTagId);
	}
	
	this.handleUpdate = function()
	{
		if(this.xmlHttpObj.readyState == 4)
		{
			// To make sure valid response is received from the server, 200 means response received is OK
			if(this.xmlHttpObj.status == 200)
			{	
				if (this.xmlHttpObj.responseText != "") 
				{		
					//var dom = this.xmlHttpObj.responseXML;		
					
					for (var i = 0; i < this.observers.length; i++){
						this.observers[this.observers.length-1-i].execute();
					}
				}
			}
		}
	}
	
	this.handleLeadtimeUpdate = function(xmlHttpObj)
	{
		// XPATH
		//var leadtimes = xmlHttpObj.responseXML.selectSingleNode("//leadtimes");
		
		// avoid XPATH
		var leadtimes = xmlHttpObj.responseXML.getElementsByTagName("leadtimes")[0];
		
		if (leadtimes)
		{
			for (var i = 0; i < leadtimes.childNodes.length; ++i)
			{
				var leadtimeNode = leadtimes.childNodes[i];
				if (leadtimeNode.nodeType == Node.ELEMENT_NODE &&
					leadtimeNode.nodeName == "leadtime")
				{
					var attributes = leadtimeNode.attributes;
					
					var productRef = "";
					var leadtime = "";
					
					for (var j = 0; j < attributes.length; j++ )
					{
						if (attributes[j].name == "productref")
							productRef = attributes[j].value
							
						if (attributes[j].name == "value")
							leadtime = attributes[j].value								
					}
											
					for (var k = 0; k < this.leadtimeProductRefs[productRef].length; ++k)
					{
						document.getElementById(this.leadtimeProductRefs[productRef][k]).innerHTML = leadtime;
					}
				}
			}
		}
	}
	
	this.handlePriceUpdate = function(xmlHttpObj)
	{
		// XPATH
		// var prices = xmlHttpObj.responseXML.selectSingleNode("//productprices");
		
		// avoid XPATH
		var prices = xmlHttpObj.responseXML.getElementsByTagName("productprices")[0];
		
		if (prices)
		{
			for (var i = 0; i < prices.childNodes.length; ++i)
			{
				var priceNode = prices.childNodes[i];
				if (priceNode.nodeType == Node.ELEMENT_NODE &&
					priceNode.nodeName == "price")
				{
					var attributes = priceNode.attributes;
					
					var productRef = "";
					var price = "";
					
					for (var j = 0; j < attributes.length; j++ )
					{
						if (attributes[j].name == "productref")
							productRef = attributes[j].value
							
						if (attributes[j].name == "value")
							price = attributes[j].value								
					}
					
					
					for (var k = 0; k < this.priceProductRefs[productRef].length; ++k)
					{
						document.getElementById(this.priceProductRefs[productRef][k]).innerHTML = price;
					}
				}
			}
		}
	}
}


function ContextFixer(func, context) 
{
    /* Make sure 'this' inside a method points to its class */
    this.func = func;
    this.context = context;
    this.args = arguments;
    var self = this;

    this.execute = function() {
        /* execute the method */
        var args = new Array();

        // the first arguments will be the extra ones of the class
        for (var i=0; i < self.args.length - 2; i++) {
            args.push(self.args[i + 2]);
        };

        // the last are the ones passed on to the execute method
        for (var i=0; i < arguments.length; i++) {
            args.push(arguments[i]);
        };
        self.func.apply(self.context, args);
    };
};
