function Filtertable() {
	
	this.initialize = function(handle, storagePre, columnCount, useUpper, useCategories, isNormalFiltertable, showPictures, ndd1, ndd2, ndd3, ndd4) {
		this.handle = handle;
		this.storagePre = storagePre;
		this.columnCount = columnCount;
		this.useUpper = useUpper;
		this.useCategories = useCategories;
		this.isNormalFiltertable = isNormalFiltertable;
		this.showThePictures = showPictures;
		this.noDropdown1Array = new Array();
		this.noDropdown1Array[1] = ndd1;
		this.noDropdown1Array[2] = ndd2;
		this.noDropdown1Array[3] = ndd3;
		this.noDropdown1Array[4] = ndd4;
		this.fadeCount = 0;

		var imageDiv = document.getElementById('filter-img-init');
		if(imageDiv) {
			var image = imageDiv.getElementsByTagName('img')[0];
			if(image) {
				this.initialImage = image.src;
			}
		}
		
		try {
			document.execCommand("BackgroundImageCache", false, true);
		} catch(e) {
			// This is needed to remove the Background-Image-Flicker in IE during transitions
			// Will always throw an exception in Firefox
		}
		

		//instantiate an ajax object
		this.ajaxConnector = new AJAXConnector( );
		ajaxConnector.registerDataHandler( this.replaceTable );
		ajaxConnector.setMaxRequestTime(5000);
	
	
		this.selectValues = new Array();
		this.selectValuesOld = new Array();
		for(var i = 1; i < columnCount; i++) {
			if(this.useUpper) {
				var upperSelect = document.getElementById("upper" + i);				
			}
			var lowerSelect = document.getElementById("lower" + i);
			var lowestSelect = document.getElementById("lowest" + i);

			// if the lower has only one value then reset the upper
			if(this.useUpper && (lowerSelect.length == 1)) {
				upperSelect.selectedIndex = 0;
			}

			if(this.useUpper) {
				if(upperSelect.selectedIndex == 0) {
					lowerSelect.disabled = true;
					if(lowestSelect){
						lowestSelect.disabled = true;
					}
				}
				this.selectValues["upper" + i] = upperSelect.selectedIndex;
				this.selectValuesOld["upper" + i] = "0";
				// Now set initial images in case of preset values
				if(this.showThePictures && upperSelect.selectedIndex != 0) {
					var initialImageDiv = document.getElementById('filter-img-init');
					var initialImage = initialImageDiv.getElementsByTagName('img')[0];
					initialImage.style.display = "none";
					var imageDiv = document.getElementById('filter-img-' + i);
					var newImage = new Image();
					newImage.src = filtertableImages[upperSelect.selectedIndex][lowerSelect.selectedIndex];
					imageDiv.appendChild(newImage);
				}
			}
			else{
				this.selectValues["upper" + i] = this.noDropdown1Array[i];
				this.selectValuesOld["upper" + i] = "0";
			}

			// #BUG 28157: lowerSelect might be null. AVOID an exception or the script terminates! 
			if(lowerSelect != null){
				this.selectValues["lower" + i] = lowerSelect.selectedIndex;
				this.selectValuesOld["lower" + i] = "0";
			}
			
			
			if(lowestSelect){
				this.selectValues["lowest" + i] = lowestSelect.selectedIndex;
				this.selectValuesOld["lowest" + i] = "0";
			}
			else{
				this.selectValues["lowest" + i] = "0";
				this.selectValuesOld["lowest" + i] = "0";
			}
		}
		
		
		// save me!
		document.filtertable = this;		
	}

	this.changeUpper = function(option, form, upperName) {
		this.event = upperName;
	
		// Remember upper values
		this.selectValuesOld[upperName] = this.selectValues[upperName];
		this.selectValues[upperName] = option;
		
		var lowerName = "lower" + upperName.substr("upper".length);
		var lowestName = "lowest" + upperName.substr("upper".length);
		
		// Remember lower values
		this.selectValuesOld[lowerName] = this.selectValues[lowerName];
		this.selectValues[lowerName] = "0";
		
		// Enable/Disable lower select
		if(form[upperName].selectedIndex == 0) {
			form[lowerName].disabled = true;
		} else {
			form[lowerName].disabled = false;
		}
		// Disable lowest select
		if(form[lowestName]){
			form[lowestName].disabled = true;
		}

		// set the options for the lower dropdown
		var length = form[lowerName].length;
		for(var i = 1; i < length; i++) {
			form[lowerName].remove(1);
		}
		if(option != 0) {
			for (var i = 0; i < (dropdown1[option - 1]).length; i++){
				newOption = new Option((dropdown1[option - 1][i][0]), (dropdown1[option - 1][i][1]), false, false);
		  		form[lowerName].options[form[lowerName].length] = newOption;
			}
		}
		// set the options for the lowest dropdown if available
		if(document.getElementById("lowest1")){
			for(var i = 0; i < form[lowestName].length; i++) {
				form[lowestName].remove(1);
			}
			// Insert new options
			var upperSelect = this.selectValues[upperName];
			if(upperSelect != 0 && option != 0) {
				var currentUpper = dropdown1[upperSelect - 1];
				if(currentUpper[option - 1]){
					for (var i = 2; i < (currentUpper[option - 1]).length; i++){
						newOption = new Option((currentUpper[option - 1][i][0]), (currentUpper[option - 1][i][1]), false, false);
				  		form[lowestName].options[form[lowestName].length] = newOption;
					}
				}
			}
		}
		
		this.sendRequest();
	}	
		
	
	this.changeLower = function(option, form, lowerName) {
		this.event = lowerName;
		var curNumber = lowerName.substr("lower".length);
		var upperName = "upper" + curNumber;
		var lowestName = "lowest" + curNumber;
	
		// Remember lower values
		this.selectValuesOld[lowerName] = this.selectValues[lowerName];
		this.selectValues[lowerName] = option;
		this.selectValuesOld[lowestName] = this.selectValues[lowestName];
		this.selectValues[lowestName] = 0;
		
		//the following part is not needed if the category dropdown box 
		//has been used (curNumber == 0)
		if(curNumber != 0){
			
			// Enable/Disable lowest select
			if(document.getElementById("lowest1")){
				if(form[lowerName].selectedIndex == 0) {
					form[lowestName].disabled = true;
				}
				else {
					form[lowestName].disabled = false;
				}
			}
			
			var upperSelect = this.selectValues[upperName];
			if(this.useUpper) {
				// Remember upper values
				var upperName = "upper" + lowerName.substr("lower".length);
				this.selectValuesOld[upperName] = this.selectValues[upperName];
			}
			
			// set the options for the lowest dropdown if available
			if(document.getElementById("lowest1")){
				for(var i = 0; i < form[lowestName].length; i++) {
					form[lowestName].remove(1);
				}
				// Insert new options
				if(upperSelect != 0 && option != 0) {
					var currentUpper = dropdown1[upperSelect - 1];
					for (var i = 2; i < (currentUpper[option - 1]).length; i++){
						newOption = new Option((currentUpper[option - 1][i][0]), (currentUpper[option - 1][i][1]), false, false);
				  		form[lowestName].options[form[lowestName].length] = newOption;
					}
				}
			}
		}//end of if(curNumber == 0)
		
		this.sendRequest();
	}
	
	// NEW for 9.7
	this.changeLowest = function(option, lowestName){
		this.event = lowestName;
		
		// Remember lowest values
		this.selectValuesOld[lowestName] = this.selectValues[lowestName];
		this.selectValues[lowestName] = option;
		
		if (this.useUpper){
			// Remember upper values
			var upperName = "upper" + lowestName.substr("lowest".length);
			this.selectValuesOld[upperName] = this.selectValues[upperName];
		}
		
		this.sendRequest();
	}

	this.setImages = function() {
		if(this.initialImage) {
			var anythingSelected = false;
			for(var i=1; i<this.columnCount; i++) {
				var imageDiv = document.getElementById('filter-img-' + i);
				var imageIndex = document.getElementById('upper' + i).selectedIndex;
				var lowerImageIndex = document.getElementById('lower' + i).selectedIndex;
				if(imageIndex != 0) {
					anythingSelected = true;
					var imageDivTemp = document.getElementById('filter-img-init');
					var imageTemp = imageDivTemp.getElementsByTagName('img')[0];
				}
				if(imageDiv) {
					var images = imageDiv.getElementsByTagName('img');
					while(images.length > 1) {
						imageDiv.removeChild(images[0]);
					}
					
					var image = imageDiv.getElementsByTagName('img')[0];
										
					if(this.theColumnToChange == i){
						if(image) {
							this.fadeOutImages.push(image);
						}
						newImage = new Image();
						if(this.event.indexOf('lower') > -1){
							newImage.src = filtertableImages[imageIndex][lowerImageIndex];
						}
						else if(imageIndex > 0){
							newImage.src = filtertableImages[imageIndex][0];
						}
						else{
							newImage.src = filtertableImages[imageIndex][lowerImageIndex];
						}
						
						newImage.style.display = "none";
						imageDiv.appendChild(newImage);

						if(imageIndex!=0) {
							this.fadeInImages.push(newImage);
						}
						if(imageTemp) {
							this.fadeOutImages.push(imageTemp);
						}
					} else {
					
						if(image) {
							image.src = filtertableImages[imageIndex][lowerImageIndex];
							
						} else {
							image = new Image();
							image.src = filtertableImages[imageIndex][lowerImageIndex];
							imageDiv.appendChild(image);
						}	
						
						this.setOpacity(image, 100);

						if(imageIndex == 0) {
							image.style.display = 'none';
						} else {
							image.style.display = '';
							var imageDivInit = document.getElementById('filter-img-init');
							var imageInit = imageDivInit.getElementsByTagName('img')[0];
							imageInit.style.display = 'none';
						}
					}
															
				} 
			}
			if(!anythingSelected) {
				var imageDiv = document.getElementById('filter-img-init');
				var image = imageDiv.getElementsByTagName('img')[0];
				image.src = this.initialImage;
				this.fadeInImages.push(image);
			}
		}
	}
	
	
	this.sendRequest = function() {
		var requestURL = this.handle;
		if(this.isNormalFiltertable) {
			requestURL += ".ajax.component.filtertable.";
		} else {
			requestURL += ".ajax.component.filtertable_mc.";
		}
		requestURL += this.storagePre;
		for(var i = 1; i < this.columnCount; i++) {
			if(this.useUpper){
				requestURL += "." + this.selectValues["upper" + i];
				requestURL += "." + this.selectValues["lower" + i];
				requestURL += "." + this.selectValues["lowest" + i];
				requestURL += "." + this.selectValuesOld["upper" + i];
				requestURL += "." + this.selectValuesOld["lower" + i];
				requestURL += "." + this.selectValuesOld["lowest" + i];
			}
			else {
				requestURL += "." + this.noDropdown1Array[i];
				requestURL += "." + this.selectValues["lower" + i];
				requestURL += "." + this.selectValues["lowest" + i];
				requestURL += "." + this.noDropdown1Array[i];
				requestURL += "." + this.selectValuesOld["lower" + i];
				requestURL += "." + this.selectValuesOld["lowest" + i];
			}
		}
		if(this.useCategories) {
			var categorySelect = document.getElementById("lower0");
			requestURL += "." + categorySelect.selectedIndex;
		}
		requestURL += ".html";
		ajaxConnector.sendRequest( requestURL, "", AJAXConnector.REQUEST_GET );
	}
	
	this.replaceTable = function(status, response, param, type, statusmsg) {
		if(status == AJAXConnector.SUCCID_LOAD) {
			try {
				var footnotesStart = response.indexOf("*");
				var footnotesEnd = response.lastIndexOf("*")+1;
				var footnotes = response.substring(footnotesStart, footnotesEnd);
				
				var tempString1 = response.substring(0, footnotesStart);
				var tempString2 = response.substr(footnotesEnd);
				var tableString = tempString1.concat(tempString2);				

				var filtertable = document.getElementById("filtertable");
				var filtertableBody = filtertable.getElementsByTagName("tbody")[0];
				
					var filtertableTemp = document.getElementById("filtertable-temp");

					document.filtertable.replaceInnerHTML(filtertableTemp, tableString);					

					var filtertableTempBody = filtertableTemp.getElementsByTagName("tbody")[0];

					document.filtertable.fadeOutElements = new Array();
					document.filtertable.fadeInRows = new Array();
					document.filtertable.fadeInColumns = new Array();
		
					// Find out what has changed
					if(document.filtertable.event.indexOf("upper") > -1) {
						// We have an upper event
						document.filtertable.theColumnToChange = document.filtertable.event.substring("upper".length);
					} else if(document.filtertable.event.indexOf("lower") > -1) {
						// We have a lower event
						document.filtertable.theColumnToChange = document.filtertable.event.substring("lower".length);
					} else {
						// We have a lowest event
						document.filtertable.theColumnToChange = document.filtertable.event.substring("lowest".length);
					}
				
					document.filtertable.diffTables(filtertableBody, filtertableTempBody);					

					document.filtertable.fadeOutImages = new Array();
					document.filtertable.fadeInImages = new Array();
					if(!document.filtertable.isNormalFiltertable && document.filtertable.showThePictures) {						
						document.filtertable.setImages();
					}
					document.filtertable.prepareDynamicFootnotes(footnotes);
					
					document.filtertable.fade();
				
					//document.filtertable.writeDynamicFootnotes(footnotes);
					
					// CR 631: Replace SLT NG Links
					if (window.msSltLinkRewriter && window.msSltLinkRewriter.replaceSltLinks) {
						window.msSltLinkRewriter.replaceSltLinks();
					}
			} catch(exc)  {
			
				alert(exc.message);
			}
		} else {
			alert(statusmsg);
		}	
	}
	
	this.diffTables = function(oldElement, newElement) {
		var oldElementRows = oldElement.rows;
		var newElementRows = newElement.rows;
		
		// Only change the footnotes if the leftmost column changes
		this.changeFootnotes = (newElementRows.length != oldElementRows.length)||(this.theColumnToChange == 0);
		
		for(var rowId = 0; rowId < oldElementRows.length; rowId++) {

			if(((newElementRows.length == oldElementRows.length) || (rowId < (newElementRows.length - 2) && rowId < (oldElementRows.length - 2))) && this.theColumnToChange != 0) {
				// Do we have this row still in the new table??
				document.filtertable.fadeOutElements.push(oldElementRows[rowId].cells[document.filtertable.theColumnToChange].firstChild);
				newElementRows[rowId].cells[document.filtertable.theColumnToChange].firstChild.style.display = "none";
				document.filtertable.fadeInColumns.push(rowId);
			} else {
				document.filtertable.fadeOutElements.push(oldElementRows[rowId]);
			}
		}
		if(this.theColumnToChange == 0) {
			for(var rowId = 0; rowId < newElementRows.length; rowId++) {
					document.filtertable.fadeInRows.push(rowId);
			}
		}
		var length = (oldElementRows.length > 2)? oldElementRows.length - 2 : 0;
		if(newElementRows.length != oldElementRows.length) {
			for(var rowId = length; rowId < newElementRows.length; rowId++) {
				newElementRows[rowId].style.display = "none";
				document.filtertable.fadeInRows.push(rowId);
			}
		}
	}
	
	this.fade = function() {
		this.fadeCount++;
		this.fadeOut(100, this.fadeCount);
	}

	this.fadeIn = function(opacity, fadeCount) {
		if(fadeCount != this.fadeCount) return;
	
		var filtertable = document.getElementById("filtertable");
		var filtertableBody = filtertable.getElementsByTagName("tbody")[0];
		
		for(var i = 0; i < this.fadeInRows.length; i++) {
		    object = filtertableBody.rows[this.fadeInRows[i]];
		    if(opacity == 0) {
				object.style.display = "";
			}
	    	if (opacity <= 100) {
		    	this.setOpacity(object, opacity);			    
		    }
		}
		for(var i = 0; i < this.fadeInColumns.length; i++) {
			object = filtertableBody.rows[this.fadeInColumns[i]].cells[this.theColumnToChange].firstChild;
		    if(opacity == 0) {
				object.style.display = "";
			}
	    	if (opacity <= 100) {
		    	this.setOpacity(object, opacity);			    
		    }
		}

		if(this.theColumnToChange == 0) {
			filtertableBody.style.display = "";
		}
		
		for(var i = 0; i < this.fadeInImages.length; i++) {
			object = this.fadeInImages[i];
		    if(opacity == 0) {
				object.style.display = "";
			}
	    	if (opacity <= 100) {
		    	this.setOpacity(object, opacity);			    
		    }
		}
				
		var footnotesTag = document.getElementById("ms-footnote-dyn");
		if(footnotesTag && this.changeFootnotes) {
			footnotesTag.style.display = "";
			this.setOpacity(footnotesTag, opacity);	
		}
			
		if(opacity <= 100) {
	      opacity += 5;
	      window.setTimeout("document.filtertable.fadeIn("+opacity+", "+fadeCount+")", 50);
	    }
	}

	this.fadeOut = function(opacity, fadeCount) {		
		if(fadeCount != this.fadeCount) return;

		if ((opacity >= 0) &&  !(this.fadeOutElements.length == 0 && this.fadeOutImages.length == 0)) {
			for(var i = 0; i < this.fadeOutElements.length; i++) {	
			    object = this.fadeOutElements[i];
			    this.setOpacity(object, opacity);			    
			}
			for(var i = 0; i < this.fadeOutImages.length; i++) {
				object = this.fadeOutImages[i];
				this.setOpacity(object, opacity);		
			}
			
			var footnotesTag = document.getElementById("ms-footnote-dyn");
			if(footnotesTag && this.changeFootnotes) {
				this.setOpacity(footnotesTag, opacity);	
			}
			
	       opacity -= 5;
	   	   window.setTimeout("document.filtertable.fadeOut("+opacity+", "+fadeCount+")", 50);
       } else {
       		for(var i = 0; i < this.fadeOutImages.length; i++) {
				object = this.fadeOutImages[i];
				object.style.display = "none";	
			}
       		
       
 			var filtertable = document.getElementById("filtertable");
			var filtertableBody = filtertable.getElementsByTagName("tbody")[0];

			if(this.theColumnToChange == 0) {
				filtertableBody.style.display = "none";
	        }

			  var filtertableTemp = document.getElementById("filtertable-temp");
              var filtertableTable = filtertable.getElementsByTagName("table")[0];
              
              var filtertableTempTable = filtertableTemp.getElementsByTagName("table")[0];
              var filtertableTempBody = filtertableTempTable.tBodies[0].cloneNode(true);
              
              filtertableTable.replaceChild(filtertableTempBody, filtertableTable.tBodies[0]);
              
            var footnotesTag = document.getElementById("ms-footnote-dyn");
            
            
			if(footnotesTag && this.changeFootnotes) {
				footnotesTag.style.display = "none";
				this.setOpacity(footnotesTag, opacity);	
				footnotesTag.innerHTML = this.dynamicFootnoteString;
			}
              
 			  this.fadeIn(0, fadeCount);
	   }
	}

	this.setOpacity = function(obj, opacity) {
	  //opacity = (opacity == 100)?99.999:opacity;
	  
	  if(/MSIE/.test(navigator.userAgent) && !window.opera) {
		  obj.style.zoom = 1;
		  obj.style.filter = "alpha(opacity="+opacity+")";
		  // #### Another workaround for an IE bug - BEGIN ####
		  // The following loop is only needed because IE has some bugs that prevent 
		  // implementing transparency the simple way :-(
		  var backgroundColor = "#ffffff";
		  for(var i = 0; i < obj.childNodes.length; i++) {
		  	if(obj.childNodes[i].nodeName != "#text") {
			  	obj.childNodes[i].style.zoom = 1;	
			  	obj.childNodes[i].style.filter = "alpha(opacity="+opacity+")";			  	
			  	for(var j = 0; j < obj.childNodes[i].childNodes.length; j++) {
				  	if(obj.childNodes[i].childNodes[j].nodeName != "#text") {
					  	obj.childNodes[i].childNodes[j].style.zoom = 1;									  		  	
					  	obj.childNodes[i].childNodes[j].style.filter = "alpha(opacity="+opacity+")";
					  	for(var k = 0; k < obj.childNodes[i].childNodes[j].childNodes.length; k++) {
						  	if(obj.childNodes[i].childNodes[j].childNodes[k].nodeName != "#text") {
							  	obj.childNodes[i].childNodes[j].childNodes[k].style.zoom = 1;							  	
							  	obj.childNodes[i].childNodes[j].childNodes[k].style.filter = "alpha(opacity="+opacity+")";
							}
					  	}
					}
			  	}
			 }
		  }
	  }
	  // #### Another workaround for an IE bug - END ####
	  obj.style.KHTMLOpacity = opacity/100;
	  obj.style.MozOpacity = opacity/100;
	  obj.style.opacity = opacity/100;
	}	
	
	this.replaceInnerHTML = function(object, htmlString) {
		try {
			objectBody = object.getElementsByTagName("tbody")[0];
			objectBody.innerHTML = htmlString;
		} catch(exc) {
			// some workaround for a stupid bug in ie, that doesn't let you change the inner of a table via innerHTML
			var objectString = object.innerHTML;
			var objectStringBefore = "";
			if(objectString.indexOf("<TBODY>") > -1) {
				objectStringBefore = objectString.substring(0, objectString.indexOf("<TBODY>") + "<TBODY>".length);
			} else {
				objectStringBefore = objectString.substring(0, objectString.indexOf("<TBODY style=\"DISPLAY: none\">") + "<TBODY style=\"DISPLAY: none\">".length);
			}
			var objectStringAfter = objectString.substring(objectString.indexOf("</TBODY>"));	
			objectString = objectStringBefore + htmlString + objectStringAfter;	
			object.innerHTML = objectString;	
		}

	}
	
	this.prepareDynamicFootnotes = function(footnotesString) {
		var footnotes = footnotesString.split("*");
		strFootnote = "";
		
		for (var i=0; i<footnotes.length; i++) {
			if (footnotes[i] != "") {
				strFootnote += '<p class="ms-text ms-tx3">';
				strFootnote += footnotes[i];
				strFootnote += '</p>';
			}
		}
		
		this.dynamicFootnoteString = strFootnote;
	}
}