// Login
function loginUser()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/loginUser");
    
    // Daten aufbauen und ins Fenster laden
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    // document.forms[0].removeChild($("ek_ajax_url"));
	$("ek_ajax_url").remove();
}

// Funktion des Dialogs "IDD_MAIN" zur Ermittlung
// des Zustands des Popupblockers. Veranlasst die
// Prüfung der Aktivität des Blockers und sperrt
// das System, sofern er aktiviert ist
function testPopupBlocker(status)
{
    var formData = Form.serialize(document.forms[0]);
    var browserType = (is.ie) ? "InternetExplorer" : ((is.nav) ? "Firefox" : "unknown");
    
    new Ajax.Request("ajax/testPopupBlocker", {
        parameters:
        {
            '__eksubmit_values__' : formData + "&status=" + status + "&browserType=" + browserType
        },
        
        onSuccess: function(transport)
        {
            try
            {
				var responseObject = transport.responseJSON;
				responseObject.popupCheck.evalScripts();
            }
            catch(e)
            {
                alert("Fehler beim Testen des Popup-Blockers.\nException: " + e.message);
            }
        }
    });
}


// Funktion der Dialoge "IDD_MAIN" und "IDD_PRODUCT" zum
// Laden der drei HTML-Bereiche des Dialogs "IDD_MAIN"
function loadHtmlPage(htmlPagePosition)
{
    var formData = Form.serialize(document.forms[0]);
    
    new Ajax.Request("ajax/loadHtmlPage", {
        parameters:
        {
            '__eksubmit_values__' : formData + "&position=" + htmlPagePosition
        },
        
        onSuccess: function(transport)
        {
            try
            {
				// Retrieve all information of the HTML page or
				// fragment to load provided by the server
				var responseObject = transport.responseJSON;
				
				// Fetch the DOM element of the main dialog
				// where the HTML content should get displayed
				var pageElement;
				if(htmlPagePosition == "UPPER_HEADER")
					pageElement = topEasykatFrame.$("IDC_UPPER_HEADER_HTMLPAGE");
				else if(htmlPagePosition == "LOWER_HEADER")
					pageElement = topEasykatFrame.$("IDC_LOWER_HEADER_HTMLPAGE");
				else if(htmlPagePosition == "FOOTER")
					pageElement = topEasykatFrame.$("IDC_FOOTER_HTMLPAGE");
				
				// Load the contents into the page element
				if(pageElement)
				{
					// If it's not the upper header being loaded
					// and a logo image is present, too
					if(!(htmlPagePosition == "UPPER_HEADER" && responseObject.htmlPageContent == "<div></div>"))
					{
						// Fetch the header of the HTML document repre-
						// senting the main catalog dialog
						var mainDocumentHeader = topEasykatFrame.document.getElementsByTagName("head")[0];
						
						// Insert new <head> nodes for all JavaScript
						// related tags (file references or inline code)
						// of this header or footer HTML page
						for(var i = 0; i < responseObject.headerContent.javaScriptLinks.length; i++)
						{
							// Setup new document node and set its type
							var newScript = document.createElement('script');
							newScript.type = 'text/javascript';
							
							// Add corresponding information, depending
							// on whether this is a file reference or
							// inline code tag
							if(responseObject.headerContent.javaScriptLinks[i].tagType == "fileLink")
								newScript.setAttribute("src", responseObject.headerContent.javaScriptLinks[i].data);
							else
								newScript.text = responseObject.headerContent.javaScriptLinks[i].data;
							
							// Append the node to the header of main dialog
							mainDocumentHeader.appendChild(newScript);
						}
						
						// Insert new <head> nodes for all CSS styles
						// related tags (file references or inline data)
						// of this header or footer HTML page
						for(var i = 0; i < responseObject.headerContent.stylesheetLinks.length; i++)
						{
							// Variable holding new node to insert
							var newStyleData;
							
							// If this tag is a file reference
							if(responseObject.headerContent.stylesheetLinks[i].tagType == "fileLink")
							{
								newStyleData = document.createElement('link');
								newStyleData.setAttribute("type", 'text/css');
								newStyleData.setAttribute("rel", "stylesheet");
								newStyleData.setAttribute("href", responseObject.headerContent.stylesheetLinks[i].data);
							}
							// If this tag represents inline style data
							else
							{
								newStyleData = document.createElement('style');
								newStyleData.setAttribute("type", 'text/css');
								newStyleData.setAttribute("media", "screen");
								
								// Load inline style information into cor-
								// rect attribute of node which differs
								// depending on the browser used
								// Internet Explorer
								if(newStyleData.styleSheet)
									newStyleData.styleSheet.cssText = responseObject.headerContent.stylesheetLinks[i].data;
								// FireFox and other browsers
								else
								{
									var styleNode = document.createTextNode(responseObject.headerContent.stylesheetLinks[i].data);
									newStyleData.appendChild(styleNode);
								}
							}
							
							// Append the node to the header of main dialog
							mainDocumentHeader.appendChild(newStyleData);
						}
						
						// Replace the current content of the corresponding
						// header or footer dialog section with the HTML
						// data the page to load provides and display it
						pageElement.update(responseObject.htmlPageContent);
						pageElement.show();
						
						// If an onload action has been defined within the
						// <body> tag of the HTML page to load
						if(responseObject.onloadAction)
						{
							// Wrap the onload action JavaScript code in
							// another function in order to ensure, that
							// the 'this' keywords references the correct
							// dataset, which is the <body> element in
							// this case
							var onloadFunctionCall = function() {
								// Retrieve the special <div> element which
								// is the replacement of the <body> element
								// of the page to load, because it would
								// have been ignored by the browser due to
								// its insertion into a <div> container
								var newBodyElement = pageElement.select("[bodyReplacement='true']")[0];
								
								// Re-establish function character of the
								// onload attribute string, so it can be
								// executed
								var newOnloadFunction = new Function(responseObject.onloadAction);
								
								// Trigger the onload routine setup before
								// within the scope of the special body-
								// replacement <div> element, as it would
								// have been done by the browser, too
								newOnloadFunction.apply(newBodyElement);
							};
							
							// Delay the performance of the newly construc-
							// ted onload function, so the browser has
							// enough time to load all JavaScript and
							// stylesheet data added previously
							setTimeout(function() { onloadFunctionCall.defer(); }, 100);
						}
					}
				}
            }
            catch(e)
            {
                alert("Fehler beim Laden der HTML-Seite '" + htmlPagePosition + "'\nException: " + e.message);
            }
        }
    });
}


/**
*	Inform server about a tab change within product dialog (IDD_PRODUCT), so this
*	tab can get re-selected automatically, if product group is switched (assumed
*	that this kind of tab is also available for the new product group)
*
*	@param event {Object}: HTML event object passed by invoking event handler
*/
function setActiveTab(event)
{
	// Fetch the data the server needs to fulfill the
	// Ajax request for the BOM data
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	
    new Ajax.Request("ajax/setActiveTab", {
        parameters:
        {
            '__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&activeTabId=" + this.getAttribute("panelid")
        },
        
        onSuccess: function(transport)
        {
		}
	});
}


/**
*	Build BOM table using an Ajax request to fetch required information
*/
function loadBomTable()
{
	// Fetch the data the server needs to fulfill the
	// Ajax request for the BOM data
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	
    new Ajax.Request("ajax/getBomTable", {
        parameters:
        {
            '__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId
        },
        
        onSuccess: function(transport)
        {
            try
            {
				// Get the response data as an object
				var responseObject = transport.responseJSON;
				
				// Adjust the buttons displayed in the control
				// buttons table to reflect the BOM tab's actions
				adjustCfgControlButtonsTable();
				
				// Setup the HTML element for the BOM table and
				// set the correct attributes to establish a good
				// layout
				var matlistTable = document.createElement("table");
				matlistTable.id = "IDC_MATLIST_TABLE";
				matlistTable.className = "easykatLight-matlistTable";
				matlistTable.cellSpacing = "0";
				matlistTable.cellPadding = "0";
				matlistTable.style.width = "100%";
				
				// Setup the table's content row by row and cell
				// by cell as provided by the Ajax response
				for(var i = 0; i < responseObject.length; i++)
				{
					var currentRow = matlistTable.insertRow(i);
					
					// Setup the alternating row color style
					if(i % 2 == 0)
						currentRow.className = "altrow";
					
					for(var j = 0; j < responseObject[i].length; j++)
					{
						var currentCell = currentRow.insertCell(j);
						
						currentCell.innerHTML = responseObject[i][j].data;
						
						// Set the correct style depending on the
						// type of data to display
						if(responseObject[i][j].type == "default")
							currentCell.className = "";
						else if(responseObject[i][j].type == "price")
						{
							currentCell.className = "priceData";
							
							// If it's a substructure link, add a
							// special style to the cell to allow
							// a different appearance
							if(responseObject[i][j].isSubstructureLink)
								currentCell.className += " subStructurePrice";
						}
						else if(responseObject[i][j].type == "quantity")
							currentCell.className = "quantityData";
						
						// Setup the style for the header row and
						// remove its alternating row color style
						if(i == 0)
						{
							currentCell.className += " header";
							currentRow.className = "";
						}
					}
				}
				
				// Retrieve the DIV element which should contain
				// the BOM table and hide it to be able to adjust
				// the table's width, if necessary, without pro-
				// ducing fickering
				var matlistTableContainer = document.getElementById("IDC_MATLIST_TABLE_CONTAINER");
				matlistTableContainer.style.visibility = "hidden";
				
				// Insert the table to the container or append it,
				// if it's generated for the first time
				if(matlistTableContainer.childNodes.length > 0)
					matlistTableContainer.replaceChild(matlistTable, matlistTableContainer.firstChild);
				else
					matlistTableContainer.appendChild(matlistTable);
				
				// Correct the table width, if necessary (only IE)
				// and display the table. The delay is necessary
				// to let the browser build the DOM structure of
				// the table and set the width and height values
				setTimeout(function() {
					if ((matlistTable.offsetHeight > matlistTableContainer.offsetHeight) && (matlistTable.offsetWidth == matlistTableContainer.offsetWidth))
						matlistTable.style.width = matlistTableContainer.clientWidth + 'px';
					
					matlistTableContainer.style.visibility = "visible";
				}, 5);
			}
			catch(e)
			{
				alert("Error loading the BOM data. \nException: " + e.message);
			}
		}
	});
}


// Funktion der Dialoge IDD_PRODUCT und IDD_CFGSUMMARY zum
// Hinzufügen eines Produktes zur Projektliste
function	addToShoppingCart(artNr, typecode, treeIdent, unitPrice, cfgProduct, lastDialog)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/addToShoppingCart?artNr="+artNr+"&treeIdent="+treeIdent+"&typecode="+typecode+"&unitPrice="+unitPrice+"&cfgProduct="+cfgProduct+"&lastDialog="+lastDialog);
    
    ekSubmit("", 'isyiframe' );
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
    
    // Event-Vererbung aufhalten, um die Selektion von mehreren
    // Tabellenzeilen in der Produkttabelle zu vermeiden
    if ( is.ie5up )
        Event.stop( window.event );
}


// Funktion der Dialoge IDD_PRODUCT zum
// Hinzufügen eines Produktes zur Favoritenliste
function	addToFavoriteList(artNr, typecode, treeIdent, unitPrice, cfgProduct, lastDialog)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/addToFavoriteList?artNr="+artNr+"&treeIdent="+treeIdent+"&typecode="+typecode+"&unitPrice="+unitPrice+"&cfgProduct="+cfgProduct+"&lastDialog="+lastDialog);
    
    ekSubmit("", 'isyiframe' );
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
    
    // Event-Vererbung aufhalten, um die Selektion von mehreren
    // Tabellenzeilen in der Produkttabelle zu vermeiden
    if ( is.ie5up )
        Event.stop( window.event );
}


// Funktion der Dialoge IDD_PRODUCT und IDD_PRODUCT_GROUPS zum
// Anzeigen eines vergrößerten Produktbildes in einem separaten
// Fenster. Die Funktion wird ebenfalls vom Dialog IDD_CONFIG
// zur Anzeige eines vergrößerten Vorschaubildes verwendet.
// @param imagePath - Relativer Pfad der Bilddatei, die von der
//                    Runtime Engine als Quelle genutzt wird
// @param pictureType - Gibt an, welcher Typ von Bild angezeigt
//                      werden soll. Zulässig ist eines der
//						folgenden Schlüsselwörter:
//						PRODUCT = Anzeige eines Produktbildes
//						EXTCONFIG = Anzeige eines Vorschaubil-
//								    des der aktuellen externen
//								    Konfiguration
function	displayZoomedImage(imagePath, pictureType)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    var imageData = encodeURIComponent("{'imagePath' : '" + imagePath + "'}");
    createNewHiddenFormField("ek_ajax_url", "ajax/displayZoomedImage?imageData=" + imageData + "&pictureType=" + pictureType);
    
	// Alle Eingabekontrollen des Dialogs deaktivieren
	disableInput();
	
    // Popup-Fenster für die Bilddarstellung öffnen
    window.open("","ZoomedImageWindow","width=1000,height=800,left=0,top=0,resizable=yes, scrollbars=no");
    
    // Daten aufbauen und ins Fenster laden
    ekSubmit("", 'ZoomedImageWindow');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs "IDD_PRODUCT" zur Anzeige von erweiterten
// Produktinformationen in einem den aktuellen Dialog überlagern-
// den <div>-Element
// @param infoIdent - Der Identifier für die anzuzeigenden Infor-
//        mationen (wird zur Datenbank-Abfrage benutzt)
function getProductInfos(infoIdent)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/getProductInfos?infoIdent=" + infoIdent);
    
	// Alle Eingabekontrollen des Dialogs deaktivieren
	disableInput();
	
    // Daten aufbauen und ins Fenster laden
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_CONFIG zum ermitteln
// des initialien Preises der Konfiguration un-
// mittelbar nach deren Start
function getCfgInitPrice()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/getCfgInitPrice");
    
	// Alle Eingabekontrollen des Dialogs deaktivieren
	disableInput();
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


/*
*	Function used by the dialog IDD_PRODUCT to reset all
*	items or a specific element of the product filter
*	(clear edit fields and change the selection of combo-
*	boxes to the entry chosen after initialization)
*
*	@param filterCellItems {Array}: Array containing re-
*		   ferences to all DOM elements representing a
*		   certain filter item (comboboxes and edit
*		   fields) which should be reset. If null is
*		   passed, all filters will be reset
*/
function resetProductFilter(filterCellItems)
{   
	// Aktuell selektierten Tab abfragen und aus
	// der ID die Nummer des gewählten Produkt-
	// Tabs ermitteln
	var currentProductTab = dialog.IDC_PRODUCT_TABS.getSelected();
	
	if(currentProductTab != "PRECONFIG_TAB")
		currentProductTab = currentProductTab.substring(11);
	
	// Produktfilter-Tabelle aus DOM laden
	var productFilterTable = document.getElementById("PRODUCT_COMBOBOX_TABLE_" + currentProductTab);

	// Hide the product filter table and display the
	// waiting animation dummy table
	productFilterTable.style.display = "none";
	document.getElementById("PRODUCT_COMBOBOX_TABLE_" + currentProductTab + "_WAIT_ANIMATION").style.display = "";
	
	// If only one filter shall be reset
	if(filterCellItems)
	{
		// Reset the filter relation to the equals operator
		// (initial state), if there isn't already just one
		// relation left
		if(filterCellItems[0].options.length > 1)
			filterCellItems[0].selectedIndex = 3;
		
		// Set the filter selection to the empty value
		filterCellItems[1].selectedIndex = 0;
		
		// Empty the edit fields
		filterCellItems[2].value = "";
		filterCellItems[4].value = "";
	}
	// If all filters are affected
	else
	{
		for(var i = 0; i < productFilterTable.rows.length; i++)
		{
			for(var j = 0; j < productFilterTable.rows[i].cells.length; j++)
			{
				// Inhalt der Tabellenzelle zwischenspeichern
				var filterCellContent = productFilterTable.rows[i].cells[j].firstChild;
				
				// Sofern die Zelle einen Filter beinhaltet
				if(filterCellContent && filterCellContent.tagName == "TABLE")
				{
					// Eingabefelder ermitteln
					var inputFields = filterCellContent.rows[1].cells[0].childNodes;
					
					// Setze den Vergleichsoperator der Relationen-Combobox
					// auf "=" zurück (dritte Option), sofern es nicht be-
					// reits nur noch eine Relation gibt
					if(inputFields[0].options.length > 1)
						inputFields[0].selectedIndex = 3;
					
					// Setze die Selektion der Werte-Combobox auf leer
					inputFields[1].selectedIndex = 0;
					
					// Edit-Felder leeren (Werte löschen)
					inputFields[2].value = "";
					inputFields[4].value = "";
				}
				else
					return;
			}
		}
	}
}


// Function of dialog IDD_PRODUCT for displaying
// and hiding certain buttons of the Control-
// ButtonsTable or even the entire table depen-
// ding on tab currently selected
function setProductDialogButtons(selectedTab)
{
    // Wenn nichts übergeben wurde, wurde die
    // Funktion über onload aufgerufen, und
    // die Widget-Abfrage liefert ein korrektes
    // Ergebnis
    if(selectedTab == '')
    {
        // TabCtrl-Widget und selektierten Tab
        // abfragen
        var tabCtrl = dialog["IDC_PRODUCT_TABS"];
        selectedTab = tabCtrl.getSelected();
    }
    
	// If neither pre-configuration tab nor a pro-
	// duct tab is selected, hide whole Control-
	// ButtonsTable
	if(!selectedTab || (selectedTab.indexOf("PRODUCT_TAB") == -1 && selectedTab != "PRECONFIG_TAB"))
		$("IDC_CONRTOLBUTTONS_TABLE").hide();
	else
	{
		// Determine buttons which should be visible
		// (set flag for index of each button, ig-
		// noring empty table cells)
		var visibleButtons = [false, false, false, false, false, false];
		
		// If a product tab is selected
		if(selectedTab && selectedTab.indexOf("PRODUCT_TAB") >= 0)
		{
			// Cut number of product tab out of tab cur-
			// rently being selected in order to retrieve
			// corresponding HTML elements
			var productTabIdent = selectedTab.substring(11);
			
			// Set visibility status of print product
			// table button
			var printDocumentButton = $("IDC_PRODUCTTABLE_PRINT_PDF");
			
			if(printDocumentButton.style.visibility != "hidden")
				visibleButtons[2] = true;
			
			// If content of product tab has already
			// been generated
			if($("PRODUCT_TABLE_" + productTabIdent).tagName == "DIV")
			{
				// Set visibility status of product fil-
				// ter reset button
				if($("PRODUCT_COMBOBOX_TABLE_" + productTabIdent).tagName.toUpperCase() != "DIV")
					visibleButtons[3] = true;
			}
			else
			{
				// Set visibility status of product fil-
				// ter reset button
				if($("PRODUCT_COMBOBOX_TABLE_" + productTabIdent).tagName.toUpperCase() != "DIV" && $("PRODUCT_COMBOBOX_TABLE_" + productTabIdent).rows[0].cells[0].innerHTML != "&nbsp;")
					visibleButtons[3] = true;
			}
		}
		// If pre-configuration tab is selected
		else
		{
			// If pre-configuration tab is in configuration view
			if($F("preConfigStatus") == "inProgress")
			{
				// Enable reset button of pre-configuration
				visibleButtons[4] = true;
				
				// Check current status of pre-configuration
				// and adapt visibility of buttons to it
				if($("CURRENT_CONFIG_STATUS").value == "COMPLETE")
				{
					$("IDC_CFG_FORWARD_BOTTOM").show();
					visibleButtons[5] = true;
				}
				else
					$("IDC_CFG_FORWARD_BOTTOM").hide();
				
				if($("CURRENT_CONFIG_LEVEL").value != "0")
					visibleButtons[1] = true;
			}
			// If pre-configuration tab is in product data view
			else if($F("preConfigStatus") == "productData")
			{
				// Enable button to return to configuration view
				visibleButtons[0] = true;
				
				// Set visibility status of print product table
				// button
				var printDocumentButton = $("IDC_PRODUCTTABLE_PRINT_PDF");
				
				if(printDocumentButton.style.visibility != "hidden")
					visibleButtons[2] = true;
				
				// If content of product tab has already
				// been generated
				if($("PRODUCT_TABLE_PRECONFIG_TAB").tagName == "DIV")
				{
					// Set visibility status of product fil-
					// ter reset button
					if($("PRODUCT_COMBOBOX_TABLE_PRECONFIG_TAB").tagName.toUpperCase() != "DIV")
						visibleButtons[3] = true;
				}
				else
				{
					// Set visibility status of product fil-
					// ter reset button
					if($("PRODUCT_COMBOBOX_TABLE_PRECONFIG_TAB").rows[0].cells[0].innerHTML != "&nbsp;")
						visibleButtons[3] = true;
				}
			}
		}
		
		// Apply visibility of control buttons
		var controlButtonsTable = $("IDC_CONRTOLBUTTONS_TABLE");
		var controlButtonsTableRow = controlButtonsTable.rows[0];
		var hideTable = true;
		
		for(var i = 0; i < visibleButtons.length; i++)
		{
			if(visibleButtons[i])
			{
				controlButtonsTableRow.cells[(i+1)].style.display = "";
				hideTable = false;
			}
			else
				controlButtonsTableRow.cells[(i+1)].style.display = "none";
		}
		
		// Hide whole ControlButtonsTable, if no
		// button should be visible
		if(hideTable)
			controlButtonsTable.hide();
		else
			controlButtonsTable.show();
	}
}


/**
*	Setup product filter (displayed within product tab of IDD_PRODUCT) using an
*	Ajax request to retrieve its content
*/
function setupProductFilter()
{
	// Collect all information necessary to generate content of product filter
	// on server side
	var formData = Form.serialize(document.forms[0]);
    
    new Ajax.Request("ajax/getProductFilter", {
        parameters:
        {
            '__eksubmit_values__' : formData
        },
        
        onSuccess: function(transport)
        {
            try
            {
				// Extract product filter data which were packed as JSON object
				// on server side
				var responseObject = transport.responseJSON;
				var filterTable;
				
				// Get the currently selected tab and extract the
				// number of the product tab out of it
				var currentProductTab = dialog.IDC_PRODUCT_TABS.getSelected();
				var currentTabIdent = currentProductTab;
				
				if(currentProductTab != "PRECONFIG_TAB")
					currentTabIdent = currentTabIdent.substring(11);
				
				if(responseObject.filters || responseObject.noFiltersSpecified)
				{
					// Fetch the product filter table as well as the loading
					// status container from the DOM
					var filterTable = document.getElementById("PRODUCT_COMBOBOX_TABLE_" + currentTabIdent);
					var loadingStatusElement = document.getElementById("PRODUCT_COMBOBOX_TABLE_" + currentTabIdent + "_LOADING_STATUS");
					loadingStatusElement.innerHTML = "&nbsp;0 %";
					
					// Delete the old content, if filter table is not already
					// empty, because there were no filters necessary during
					// last presentation of this product table
					if(filterTable.tagName.toUpperCase() != "DIV")
					{
						var filterTableRows = filterTable.rows.length;
						for(var i = 0; i < filterTableRows; i++)
							filterTable.deleteRow(0);
					}
				}
				
				if(responseObject.filters)
				{
					// Start with the first filter item
					responseObject.currentFilterItem = 0;
					
					// Call a subroutine for the generation of the individual
					// filter items, so the process can be interrupted for a
					// moment after the setup of each item in order to update
					// the loading status information (no sleep function avai-
					// lable in JavaScript)
					buildProductFilterItem(responseObject, filterTable, loadingStatusElement);
				}
				else if(responseObject.noFiltersSpecified)
				{
					var filterBorder = document.createElement('div');
					filterBorder.id = "PRODUCT_COMBOBOX_TABLE_" + currentTabIdent;
					filterBorder.style.top = "0px";
					filterBorder.style.left = "0px";
					filterBorder.style.width = "758px";
					filterBorder.style.height = "1px";
					filterBorder.style.position = "absolute";
					filterBorder.className = "easykatLight-border";
					filterBorder.innerHTML = "&nbsp;"
					filterTable.parentNode.replaceChild(filterBorder, filterTable);
					
					// Hide the loading status information table
					document.getElementById("PRODUCT_COMBOBOX_TABLE_" + currentTabIdent + "_WAIT_ANIMATION").style.display = "none";
				}
				
				setProductDialogButtons(currentProductTab);
			}
			catch(e)
			{
				alert("Fehler beim Aufbau des Produktfilters\nException: " + e.message);
			}
		}
	});
}


/**
*	Build up single item (combobox control) of product filter using DOM functiona-
*	lity and refresh loading status display (percentage completed). All relevant
*	event handlers are setup by this routine, too.
*	
*	@param responseObject {Object}: Object holding filter data passed on by server.
*				It also contains some information added by routine 'setupProduct-
*				Filter' as well as this routine. This is possible, because this
*				routine is called once for each filter item and always passed the
*				same data object, so it can be modified during execution
*	@param filterTable {HTML element}: Table element representing main product
*				filter table containing all filter items as well as reset button.
*				All data generated by this routine will be added to this element
*	@param loadingStatusElement {HTML element}: Table cell element displaying loa-
*				ding status information in the form of percentage completed to the
*				user. It's refreshed each time a single filter item is built up
*				completely
*/
function buildProductFilterItem(responseObject, filterTable, loadingStatusElement)
{
	// If there are still filter items to be built
	if(responseObject.currentFilterItem < responseObject.filters.length)
	{
		// Set a helper variable for the filter item currently
		// being generated
		var i = responseObject.currentFilterItem;
		
		// If the filter's title contains only whitespaces, add
		// a protected white space to it to guarantee a correct
		// layouting (correct height of the title cell)
		if(responseObject.filters[i].title.match(/^\s+$/))
			responseObject.filters[i].title += "&nbsp;";
		
		// Setup the table for the current filter which will be
		// displayed within one cell of the product filter table
		// and insert the filter's title
		var filterTableCell = document.createElement("table");
		filterTableCell.className = "easykatLight-comboboxInnerTable";
		filterTableCell.cellSpacing = "0";
		filterTableCell.style.whiteSpace = "nowrap";
		filterTableCell.insertRow(0).insertCell(0).innerHTML = responseObject.filters[i].title;
		
		// Setup the combobox containing the filter's relations
		var relationCombobox = document.createElement("select");
		relationCombobox.id = "*." + responseObject.filterStorePath + "." + responseObject.filters[i].attributeIdent + "_RELATION";
		relationCombobox.style.width = responseObject.relationComboboxWidth + "px";
		relationCombobox.onchange = relationComboboxChange;
		
		// Add the filter's relations to the relation combobox
		for(var j = 0; j < responseObject.filters[i].relations.length; j++)
		{
			relationCombobox.options[j] = new Option(responseObject.filters[i].relations[j].value, responseObject.filters[i].relations[j].id, false, false);
			
			// If it's the empty relation, convert the display text
			// to a protected white space
			if(relationCombobox.options[j].innerHTML == "")
				relationCombobox.options[j].innerHTML = "&nbsp;";
			
			if(responseObject.filters[i].relations[j].selected)
				relationCombobox.selectedIndex = j;
		}
		
		// Setup the combobox containing the filter's values (items)
		var itemCombobox = document.createElement("select");
		itemCombobox.id = "*." + responseObject.filterStorePath + "." + responseObject.filters[i].attributeIdent;
		itemCombobox.style.width = responseObject.itemComboboxWidth + "px";
		itemCombobox.style.marginLeft = "4px";
		itemCombobox.onchange = checkFilterSubmit;
		
		// Add the filter's values (items) to the value combobox
		for(var j = 0; j < responseObject.filters[i].items.length; j++)
		{
			itemCombobox.options[j] = new Option('', responseObject.filters[i].items[j].id, false, false); 
			itemCombobox.options[j].innerHTML = responseObject.filters[i].items[j].value;
			
			if(responseObject.filters[i].items[j].selected)
				itemCombobox.selectedIndex = j;
		}
		
		// Add the comboboxes to the filter's table
		var filterComboboxContainer = filterTableCell.insertRow(1).insertCell(0);
		filterComboboxContainer.style.height = "24px";
		filterComboboxContainer.style.verticalAlign = "middle";
		filterComboboxContainer.appendChild(relationCombobox);
		filterComboboxContainer.appendChild(itemCombobox);
		
		// Add the HTML elements needed for range selection
		// abilities (either range between two values or neigh-
		// borhood (percentage value) of a certain value)
		// Input field vor lower boundary
		var inputFieldLower = document.createElement("input");
		inputFieldLower.id = "*." + responseObject.filterStorePath + "." + responseObject.filters[i].attributeIdent + "_FIRST_VALUE";
		inputFieldLower.type = "text";
		inputFieldLower.value = responseObject.filters[i].firstUserValue;
		inputFieldLower.className = "textNormal";
		inputFieldLower.style.width = parseInt((responseObject.itemComboboxWidth - 21) / 2, 10) + "px";
		inputFieldLower.style.marginLeft = "4px";
		inputFieldLower.onchange = checkFilterSubmit;
		inputFieldLower.style.display = "none";
		if(!is.ie)
			inputFieldLower.style.padding = "0px";
		filterComboboxContainer.appendChild(inputFieldLower);
		
		// Label containing the neighborhood sign (+/-)
		var plusMinusLabel = document.createElement("span");
		plusMinusLabel.appendChild(document.createTextNode(" \u00B1"));
		plusMinusLabel.style.display = "none";
		filterComboboxContainer.appendChild(plusMinusLabel);
		
		// Input field vor upper boundary
		var inputFieldUpper = inputFieldLower.cloneNode(false);
		inputFieldUpper.id = inputFieldUpper.id.replace("_FIRST_VALUE", "_SECOND_VALUE");
		inputFieldUpper.value = responseObject.filters[i].secondUserValue;
		inputFieldUpper.style.marginLeft = "5px";
		inputFieldUpper.onchange = checkFilterSubmit;
		filterComboboxContainer.appendChild(inputFieldUpper);
		
		// Label containing the percent sign (%)
		var percentLabel = document.createElement("span");
		percentLabel.appendChild(document.createTextNode(" %"));
		percentLabel.style.display = "none";
		filterComboboxContainer.appendChild(percentLabel);
		
		// Append a row to the main product filter table, if necessary,
		// and insert the generated filter to a cell
		var currentTableRow;
		if(i % responseObject.filtersPerRow == 0)
			currentTableRow = filterTable.insertRow(i / responseObject.filtersPerRow);
		else
			currentTableRow = filterTable.rows[filterTable.rows.length - 1];
		
		// Adapt the table cells to display to the chosen relation
		if(relationCombobox.selectedIndex > 4)
			relationComboboxChange.call(relationCombobox, true);
		
		currentTableRow.insertCell(i % responseObject.filtersPerRow).appendChild(filterTableCell);
		responseObject.currentFilterItem++;
		
		// Update the loading status display
		loadingStatusElement.innerHTML = "&nbsp;" + parseInt((responseObject.currentFilterItem / (responseObject.filters.length)) * 100, 10) + " %";
		
		// Continue with the next item after a short pause
		setTimeout(function() { buildProductFilterItem(responseObject, filterTable, loadingStatusElement); }, 5);
	}
	// If all filter items are present, finalize the process
	else
		finalizeProductFilter(responseObject, filterTable, loadingStatusElement);
}

/**
*	Finalize product filter table by filling up missing cells of last table row and
*	adding reset button. After table setup is complete, replace loading status dis-
*	play with it (toggle display status of corresponding HTML elements)
*
*	@param responseObject {Object}: Object holding filter data passed on by server.
*				This function evaluated just the following meta information:
*					filtersPerRow {Integer}: Number of filter elements displayed
*						within each row of product filter table
*					resetFilterTooltip {String}: Tooltip which should popup, if
*						user dwells several seconds on reset button (image element) 
*	@param filterTable {HTML element}: Table element representing main product
*				filter table containing all filter items as well as reset button.
*				All operations performed by this routine affect this element
*	@param loadingStatusElement {HTML element}: Table cell element displaying loa-
*				ding status information in the form of percentage completed to the
*				user. It's fade out as soon as filter table is ready for display
*/
function finalizeProductFilter(responseObject, filterTable, loadingStatusElement)
{
	// If there's no space left for the 'reset filter' icon column,
	// insert another row to the table
	var lastTableRow = filterTable.rows[filterTable.rows.length - 1];
	if(lastTableRow.cells.length == responseObject.filtersPerRow - 1)
		filterTable.insertRow(filterTable.rows.length);
	
	// Fill up missing cells of the table row and insert the 'reset
	// filter' icon to the last cell
	for(var i = lastTableRow.cells.length; i < responseObject.filtersPerRow; i++)
	{
		var currentTableCell = lastTableRow.insertCell(i);
		
		if(i == responseObject.filtersPerRow - 1)
		{
			var resetIconImage = document.createElement("img");
			resetIconImage.id = "IDC_RESET_FILTER_ICON";
			resetIconImage.src = "EKImage/Button/Menu_Reset_Filter.gif";
			resetIconImage.className = "easykatLight-linkImage";
			resetIconImage.style.paddingRight = "10px";
			resetIconImage.style.paddingBottom = "7px";
			resetIconImage.title = responseObject.resetFilterTooltip;
			resetIconImage.onclick = function() { resetProductFilter(null); getProductTabContent({event: 'filterReset'});};
			
			// Set the correct style information and append the
			// 'reset filter' icon cell
			currentTableCell.style.textAlign = "right";
			currentTableCell.style.verticalAlign = "bottom";
			currentTableCell.appendChild(resetIconImage);
		}
	}
	
	var selectedTab = dialog.IDC_PRODUCT_TABS.getSelected();
	
	if(selectedTab != "PRECONFIG_TAB")
		selectedTab = selectedTab.substring(11);
	
	// Delete the loading status information (percent loaded), then
	// hide the table which just contains the waiting animation
	// completely and display the generated product filter table
	loadingStatusElement.innerHTML = "&nbsp; 0 %"
	document.getElementById("PRODUCT_COMBOBOX_TABLE_" + selectedTab + "_WAIT_ANIMATION").style.display = "none";
	filterTable.style.display = "";
}


/**
*	Handler of pre-configuration tab of IDD_PRODUCT processing
*	initialization and completion events of pre-configurations.
*	All parameters have to be passed within an anonymous object.
*	
*	@param scenario {String}: Specifies the scenario to handle.
*				May be one of the following keywords:
*				- initialize: Initialize configuration structure
*					of pre-configuration process and insert it
*					into corresponding tab
*				- finalize: User has just completed pre-configu-
*					ration process. Trigger execution of client-
*					specific EasyScript in order to generate
*					product data based on results of pre-confi-
*					guration process. After this script has done
*					its work, content of pre-configuration tab
*					(configuration structure) will be overwritten
*					by product information visualized in the same
*					layout as product tab
*				- resume: Return to presentation of configuration
*					structure of pre-configuration process (over-
*					write product data dialog again by toggling
*					HTML containers involved)
*/
function handlePreConfig(params)
{
	var ajaxRequestSuccessHandler;
	
	// Retrieve status information of pre-configuration tab
	var preConfigStatus = $F("preConfigStatus");
	var preConfigEvent = $F("preConfigEvent");
	
	//alert("before: scenario = " + params.scenario + " // status = " + preConfigStatus + " // event = " + preConfigEvent);
	
	// If dialog is rebuilt due to:
	// - system language change
	// - clicking back button of main configuration dialog accessed
	//   by an entry of product data view of pre-configuration tab
	// - returning from documents dialog (back button clicked) ac-
	//   cessed by an entry of product data view of pre-configura-
	//   tion tab
	// then adapt parameters relevant for further processing depen-
	// ding on status of pre-configuration process
	if(params.scenario == "initialize" && 
	  (preConfigEvent == "languageChange" || preConfigEvent == "dialogBack" || preConfigEvent == "mainConfigBack"))
	{
		// If pre-configuration process is already complete, so
		// product data view is shown, directly restore this view
		if(preConfigStatus == "productData")
			params.scenario = "finalize";
		// If pre-configuration process is still in progress or
		// should be resumed, restore pre-configuration data view
		else 
			preConfigStatus = "available";
	}
	
	//alert("after: scenario = " + params.scenario + " // status = " + preConfigStatus + " // event = " + preConfigEvent);
	
	// Initialization of pre-configuration data view or resuming
	// it due to system language change
	if(params.scenario == "initialize")
	{
		// If pre-configuration tab is not in product data view
		// and it hasn't been initialized since last product group
		// change or system language change, yet
		if(preConfigStatus != "productData" && preConfigStatus != "inProgress")
		{
			// Ensure, that all HTML elements of product data view
			// aren't visible which might not be the case, if pro-
			// duct data view was present before product group
			// changed
			$("CONFIGURATION_CONTENT").show();
			$("PRODUCT_DATA_CONTENT").hide();
			
			// Disable dialog controls already now (don't wait until
			// config data handler is triggered), because this Ajax
			// request could already last some seconds
			disableInput();
			
			ajaxRequestSuccessHandler = function(transport)
			{
				try
				{
					// If no error occurred during preparation of
					// configuration data of pre-configuration tab
					var responseObject = transport.responseJSON;
					
					if(!responseObject.errorOccurred)
					{
						// Setup onMouseUp-Handler for OK and back button
						// of ControlButtonsTable, so they can't be trig-
						// gered by hitting Enter key while cursor is po-
						// sitioned within an edit field
						$("CFG_OK").observe("mouseup", function(event) {
							startRequest('ajax/ConfigChanged', Event.element(event), 'CFG_OK')
						});
						$("IDC_CFG_CANCEL").observe("mouseup", function(event) {
							startRequest('ajax/ConfigChanged', Event.element(event), 'CFG_CANCEL')
						});
						
						startRequest("ajax/ConfigInitialLoad");
					}
					// If an error occurred, just output its reason and
					// enable dialog again displaying empty pre-configu-
					// ration tab container
					else
					{
						$("SYSTEM_ERROR_OCCURRED").value = 1;
						checkSystemError();
						
						// Enable dialog controls again
						enableInput();
					}
				}
				catch(e)
				{
					alert("Error during initialization of pre-configuration data. \nException: " + e.message);
				}
			};
		}
		else
			setProductDialogButtons('PRECONFIG_TAB');
	}
	// Finalization of pre-configuration process or reloading of product
	// data view due to:
	// - system language change
	// - clicking back button of main configuration dialog accessed by
	//   an entry of products table contained in product data view as it
	//   was displayed last time
	// - clicking back button of another dialog which was called by
	//   clicking on a link provided by entries of table of product
	//   data view as it was displayed last time
	else if(params.scenario == "finalize")
	{
		ajaxRequestSuccessHandler = function(transport)
		{
			try
			{
				var responseObject = transport.responseJSON;
				
				// If no error occurred during generation of product ta-
				// ble data which get setup by user-specific EasyScript
				if(!responseObject.errorOccurred)
				{
					// Update status information of pre-configuration tab
					$("preConfigStatus").value = responseObject.preConfigInfo.status;
					$("preConfigEvent").value = responseObject.preConfigInfo.currentEvent;
					
					// Hide container of all HTML elements of pre-confi-
					// guration data view and display the one of product
					// data view
					$("CONFIGURATION_CONTENT").hide();
					$("PRODUCT_DATA_CONTENT").show();
					
					// Hide paging buttons, if paging is disabled
					if(responseObject.pagingEvent == "" && $("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_FIRST") != null)
					{
						$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_FIRST").hide();
						$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_PREVIOUS").hide();
						$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_INFO").hide();
						$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_NEXT").hide();
						$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_LAST").hide();
					}
					
					// Fill product data view with datasets prepared on
					// server side and consider paging functionality
					getProductTabContent({event: 'clickedOnTab', tabIdent: 'PRECONFIG_TAB', pagingEvent: responseObject.pagingEvent});
				}
				// If an error occurred, just output its reason and don't
				// switch to product data view
				else
				{
					$("SYSTEM_ERROR_OCCURRED").value = 1;
					checkSystemError();
					
					// Enable dialog controls again
					enableInput();
				}
			}
			catch(e)
			{
				alert("Fehler beim Abschluss der Vorkonfiguration. \nException: " + e.message);
			}
		}
	}
	// Resume pre-configuration process from product data view
	// (back button clicked)
	else if(params.scenario == "resume")
	{
		// Toggle visibility of container encapsulating pre-confi-
		// guration data view and the one encapsulating product
		// data view
		var productDataContainer = $("PRODUCT_DATA_CONTENT");
		productDataContainer.hide();
		$("CONFIGURATION_CONTENT").show();
		
		// Remove all contents from product data view and re-es-
		// tablish situation when pre-configuration tab got trig-
		// gered for the first time since product group change
		$("PRODUCT_COMBOBOX_TABLE_PRECONFIG_TAB_WAIT_ANIMATION").style.display = "";
		
		var productFilterTable = $("PRODUCT_COMBOBOX_TABLE_PRECONFIG_TAB");
		
		// Remove all filters the product filter table contains,
		// if it's not empty
		if(productFilterTable.tagName.toUpperCase() != "DIV")
		{
			var tableRows = productFilterTable.rows.length;
			
			for(var i = 0; i < tableRows; i++)
				productFilterTable.deleteRow(0);
			
			var tableRow = productFilterTable.insertRow(0).insertCell(0).innerHTML = "&nbsp;";
			productFilterTable.style.display = "none";
		}
		
		var oldProductTable = document.getElementById("PRODUCT_TABLE_PRECONFIG_TAB");
		var emptyProductTable = document.createElement("TABLE");
		emptyProductTable.insertRow(0).insertCell(0).innerHTML = "&nbsp;";
		emptyProductTable.id = "PRODUCT_TABLE_PRECONFIG_TAB";
		productDataContainer.replaceChild(emptyProductTable, oldProductTable);
		
		// Show paging buttons again, if they got disabled du-
		// ring last visibility phase of product data view
		if($("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_FIRST") != null && $("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_FIRST").style.display == "none")
		{
			$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_FIRST").show();
			$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_PREVIOUS").show();
			$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_INFO").show();
			$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_NEXT").show();
			$("IDC_PRODUCT_TABLE_PRECONFIG_TAB_PAGING_LAST").show();
		}
		
		// Forward user request to server, so processes necessary
		// to resume pre-configuration can be performed
		ajaxRequestSuccessHandler = function(transport)
		{
			try
			{
				var responseObject = transport.responseJSON;
				
				// Update status information variables of pre-
				// configuration
				$("preConfigStatus").value = responseObject.preConfigInfo.status;
				$("preConfigEvent").value = responseObject.preConfigInfo.currentEvent;
				
				// If data of configuration data view are still avai-
				// lable in corresponding container, just adapt con-
				// trol buttons displayed above it (visibility was
				// already changed by first lines of code processed
				// within this section)
				if(responseObject.preConfigInfo.status == "inProgress")
				{
					setProductDialogButtons('PRECONFIG_TAB');
					
					// Trigger routine enabling dialog controls again,
					// because otherwise the combobox controls, which
					// were hidden (if IE 6 is used) by a CSS style
					// class when product data view got setup and dis-
					// played, won't be displayed anymore
					if(is.ie6)
						enableInput();
				}
				// If data of configuration data view have to be re-
				// stored due to:
				// - system language change
				// - resuming pre-configuration process after having
				//   clicked back button of main configuration dialog
				//   which got accessed by an entry of products table
				//   contained in product data view as it was dis-
				//   played last time
				// - resuming pre-configuration process after having
				//   clicked back button of another dialog which was
				//   called by clicking on a link provided by entries
				//   of table of product data view as it was dis-
				//   played last time
				// then re-initialize view without resetting evaluation
				// data of pre-configuration (handled on server side)
				else
					handlePreConfig({scenario: 'initialize'});
			}
			catch(e)
			{
				alert("Fehler bei der Wiederaufnahme der Vorkonfiguration. \nException: " + e.message);
			}
		}
	}
	
	if(ajaxRequestSuccessHandler)
	{
		new Ajax.Request("ajax/handlePreConfig", {
			parameters:
			{
				'__eksubmit_values__' : "sessionid=" + $F("sessionid") + "&stateid=" + $F("stateid") + "&scenario=" + params.scenario
			},
			onSuccess: ajaxRequestSuccessHandler
		});
	}
}


// Funktion des Dialogs IDD_PRODUCT zum Laden bzw.
// Aktualisieren des Inhalts (Tabellen) eines
// PRODUCTS- oder CHILD-PRODUCTS-Tabs. Alle Para-
// meter müssen in einem anonymen Objekt überge-
// ben werden
//
// @param event - Spezifizierung, warum diese
//        Funktion aufgerufen wurde anhand eines
//        der folgenden Schlüsselwörter:
//          clickedOnTab - Der Tab wurde in der
//          Dialog-Ansicht angeklickt
//          pagingAction - Ein Paging-Button
//          wurde angeklickt
//          filterChanged - Eine Filter-Einstel-
//          lung wurde verändert
//          filterReset - Der Filter wurde zu-
//          rückgesetzt
//          treeSelectionChanged - Ein neuer
//          Knoten im Menübaum wurde gewählt
//          und der zuletzt selektierte Tab
//          war ein Produkt-Tab
// @param tabIdent - Nummer oder Identifier des
//		  ausgewählten Tabs (je nach Tab-Typ),
//        nur belegt bei den Events 'clickedOnTab'
//        und 'treeSelectionChanged'
// @param pagingEvent - Legt die durchzufuehrende
//        Aktion bei der Nutzung von Paging fest:
//          INIT - Initaler Aufbau der Tabelle
//                 Wird nur gesendet, wenn Paging
//                 aktiviert ist
//          FIRST - Erste Seite laden
//          PREVIOUS - Eine Seite zurückblättern
//          NEXT - Eine seite vorblättern
//          LAST - Letzte Seite laden
function getProductTabContent(params)
{
    // Neuladen des Tabs je nach Tab-Zustand,
    // sofern die Funktion anhand eines Klicks
    // auf einen Produkt-Tab in der Dialog-
    // Ansicht aufgerufen wurde
    if(params.event == 'clickedOnTab')
    {
        var productTabIdent = params.tabIdent;
        
		// If content has already been loaded
        if($("PRODUCT_TABLE_" + productTabIdent).tagName == "DIV")
		{
			// Just adapt visible buttons of
			// ControlButtonsTable and skip
			// rest of process
			if(productTabIdent != "PRECONFIG_TAB")
				setProductDialogButtons("PRODUCT_TAB" + productTabIdent);
			else
				setProductDialogButtons(productTabIdent);
			
			return;
		}
    }
    
    if(params.event == 'clickedOnTab' || params.event == "treeSelectionChanged")
    {
        // Paging-Event löschen, da es nicht an
        // den Server zurückgesendet werden soll
        params.pagingEvent = "";
    }
    
    // Alle Eingabekontrollen des Dialogs deaktivieren
    disableInput();
    
    // Wartemeldung einblenden (wird beim Laden
    // des Frames mittels onload ausgeblendet)
    dialog.LOADPRODUCTS_NOTICE.setText($F("WAITMESSAGE"));
    dialog.LOADPRODUCTS_NOTICE.show();
    
    if(params.pagingEvent)
    {
		var formData = Form.serialize(document.forms[0]);
		
		// Daten der Produkttabelle aktualisieren
		var currentProductTab = dialog.IDC_PRODUCT_TABS.getSelected();
		currentProductTab = currentProductTab.replace("PRODUCT_TAB", "");
		
		dialog["PRODUCT_TABLE_" + currentProductTab].update({"url": "ajax/getProductTablePagingData", "params": {'__eksubmit_values__' : formData + "&pagingEvent=" + params.pagingEvent}});
        
		// Paging-Infos anpassen
		new Ajax.Request("ajax/getProductTablePagingInfo", {
			parameters:
			{
				'__eksubmit_values__' : formData + "&pagingEvent=" + params.pagingEvent
			},
			
			onSuccess: function(transport)
			{
				try
				{
					var responseObject = transport.responseJSON;
					var selectedTabIdent = responseObject.tabIdent;
					
					var firstPageButton = document.getElementById("IDC_PRODUCT_TABLE_" + selectedTabIdent + "_PAGING_FIRST");
					var previousPageButton = document.getElementById("IDC_PRODUCT_TABLE_" + selectedTabIdent + "_PAGING_PREVIOUS");
					var pagingInfoText = document.getElementById("IDC_PRODUCT_TABLE_" + selectedTabIdent + "_PAGING_INFO");
					var nextPagingButton = document.getElementById("IDC_PRODUCT_TABLE_" + selectedTabIdent + "_PAGING_NEXT");
					var lastPagingButton = document.getElementById("IDC_PRODUCT_TABLE_" + selectedTabIdent + "_PAGING_LAST");
					
					if(!responseObject.firstButtonDisabled)
					{
						firstPageButton.src = "EKImage/Button/Paging_first.gif";
						firstPageButton.className = "easykatLight-linkImage";
						firstPageButton.onclick = function() { getProductTabContent({event: 'pagingAction', pagingEvent: 'FIRST'}); }
					}
					else
					{
						firstPageButton.src = "EKImage/Button/Paging_first_disabled.gif";
						firstPageButton.className = "";
						firstPageButton.onclick = null;
					}
					
					if(!responseObject.previousButtonDisabled)
					{
						previousPageButton.src = "EKImage/Button/Paging_previous.gif";
						previousPageButton.className = "easykatLight-linkImage";
						previousPageButton.onclick = function() { getProductTabContent({event: 'pagingAction', pagingEvent: 'PREV'}); }
					}
					else
					{
						previousPageButton.src = "EKImage/Button/Paging_previous_disabled.gif";
						previousPageButton.className = "";
						previousPageButton.onclick = null;
					}
					
					pagingInfoText.innerHTML = responseObject.infoText;
					
					if(!responseObject.nextButtonDisabled)
					{
						nextPagingButton.src = "EKImage/Button/Paging_next.gif";
						nextPagingButton.className = "easykatLight-linkImage";
						nextPagingButton.onclick = function () { getProductTabContent({event: 'pagingAction', pagingEvent: 'NEXT'}); }
					}
					else
					{
						nextPagingButton.src = "EKImage/Button/Paging_next_disabled.gif";
						nextPagingButton.className = "";
						nextPagingButton.onclick = null;
					}
					
					if(!responseObject.lastButtonDisabled)
					{
						lastPagingButton.src = "EKImage/Button/Paging_last.gif";
						lastPagingButton.className = "easykatLight-linkImage";
						lastPagingButton.onclick = function() { getProductTabContent({event: 'pagingAction', pagingEvent: 'LAST'}); }
					}
					else
					{
						lastPagingButton.src = "EKImage/Button/Paging_last_disabled.gif";
						lastPagingButton.className = "";
						lastPagingButton.onclick = null;
					}
					
					dialog.LOADPRODUCTS_NOTICE.hide();
					enableInput();
					checkSystemError();
				}
				catch(e)
				{
					alert("Fehler beim Paging der Produkttabelle. \nException: " + e.message);
				}
			}
		});
    }
	else
    {
		// Retrieve identifier of selected tab in order to determine
		// which HTML table elements to remove before product table
		// is rebuilt
		var currentProductTab = (params.tabIdent) ? params.tabIdent : dialog.IDC_PRODUCT_TABS.getSelected();
		currentProductTab = currentProductTab.replace("PRODUCT_TAB", "");
		
		var tableMain = document.getElementById("PRODUCT_TABLE_" + currentProductTab);
		var tableFixedCols = document.getElementById("PRODUCT_TABLE_" + currentProductTab + "_FC");
		var tableFixedLines = document.getElementById("PRODUCT_TABLE_" + currentProductTab + "_FL");
		var tableFixedContent = document.getElementById("PRODUCT_TABLE_" + currentProductTab + "_FIX");
		var tableRowHeaderIframe = document.getElementById("PRODUCT_TABLE_" + currentProductTab + "_FL_IFRAME");
		var tableColHeaderIframe = document.getElementById("PRODUCT_TABLE_" + currentProductTab + "_FC_IFRAME");
		
		if(tableMain && tableMain.style.width && tableMain.style.height && tableMain.style.height != "10px")
		{
			var numChildNodes = tableMain.childNodes.length;
			
			for(var i = 0; i < numChildNodes; i++)
				tableMain.removeChild(tableMain.firstChild);
		}
		if(tableFixedCols)
			tableFixedCols.parentNode.removeChild(tableFixedCols);
		if(tableFixedLines)
			tableFixedLines.parentNode.removeChild(tableFixedLines);
		if(tableFixedContent)
			tableFixedContent.parentNode.removeChild(tableFixedContent);
		if(tableRowHeaderIframe)
			tableRowHeaderIframe.parentNode.removeChild(tableRowHeaderIframe);
		if(tableColHeaderIframe)
			tableColHeaderIframe.parentNode.removeChild(tableColHeaderIframe);
		
		// Generierung des Inhalts minimal zeitver-
		// setzt starten, um die Wartemeldung anzei-
		// gen zu können
		setTimeout(function() {
			updateDialogElement('IDD_PRODUCT', 'LOAD_PRODUCT_TAB_CONTENT', false, 'PRODUCT_TAB_CONTAINER|SYSTEM_ERROR_OCCURRED', 'getProductTabContent');
			
			setCorrectProductTableSize(currentProductTab);
			setupIFrameTransparency();
			setupProductFilter();
		}, 5);
    }
}


// Funktion des Dialogs IDD_PRODUCT zum Aktualisieren
// des Inhalts (Tabellen) des PRODUCT-Tabs, sofern
// der Produkt-Tab bereits beim Aufbau selektiert ist.
// Sorgt auch dafür, dass bei einer TabCtrl ohne Tabs
// die Notice-Meldungen keinen Platz mehr benötigen.
function checkProductTabTimeliness()
{
    var selectedTab = dialog.IDC_PRODUCT_TABS.getSelected();
    
	if(selectedTab)
	{
		var productTabIdent;
		
		if(selectedTab.indexOf("PRODUCT_TAB") >= 0)
			productTabIdent = selectedTab.substring(11);
		
		if(productTabIdent)
		{
			var pagingEvent = ($F("productTablePagingEnabled") == "true") ? "INIT" : "";
			getProductTabContent({event: 'treeSelectionChanged', tabIdent: productTabIdent, pagingEvent: pagingEvent});
		}
	}
    // Wenn die TabCtrl keine Tabs hat, den Platz
    // der Notice-Meldungen freigeben
    else
        $("LOADPRODUCTS_NOTICE").hide();
}


/**
 * Function used to resize and reposition contents of product
 * datasets tab (products table and environmental elements),
 * if tabCtrl containing product tab contains stacked tabs,
 * so its contents have to fit to a smaller area in order to
 * avoid scroll bars
 *
 * @param selectedTab: ID of product tab currently selected
 */
function setCorrectProductTableSize(selectedTab)
{
	// Check, if tabCtrl contains stacked tabs which is precon-
	// dition for execution of further actions
	var numStackedTabAreas = $("IDC_PRODUCT_TABS").select("div.easykatLight-tab-area").length;
	
	if(numStackedTabAreas > 1)
	{
		var stackedTabHeight = 19;
		
		// Setup an array containing all HTML elements to re-
		// size or reposition whose entries also inform about
		// style variable which must be adapted in order to
		// do so (height or top position)
		var resizeElements = [{element: document.getElementById("PRODUCT_TABLE_" + selectedTab), styleVar: "height"}];
		
		var tableFixedCols = document.getElementById("PRODUCT_TABLE_" + selectedTab + "_FC");
		var tableColHeaderIframe = document.getElementById("PRODUCT_TABLE_" + selectedTab + "_FC_IFRAME");
		
		if(tableFixedCols)
			resizeElements.push({element: tableFixedCols, styleVar: "height"});
		if(tableColHeaderIframe)
			resizeElements.push({element: tableColHeaderIframe, styleVar: "height"});
		
		// Add all elements providing paging button (visua-
		// lized by images) because they have to be moved up
		resizeElements.push({element: $("IDC_PRODUCT_TABLE_" + selectedTab + "_PAGING_FIRST"), styleVar: "top"});
		resizeElements.push({element: $("IDC_PRODUCT_TABLE_" + selectedTab + "_PAGING_PREVIOUS"), styleVar: "top"});
		resizeElements.push({element: $("IDC_PRODUCT_TABLE_" + selectedTab + "_PAGING_INFO"), styleVar: "top"});
		resizeElements.push({element: $("IDC_PRODUCT_TABLE_" + selectedTab + "_PAGING_NEXT"), styleVar: "top"});
		resizeElements.push({element: $("IDC_PRODUCT_TABLE_" + selectedTab + "_PAGING_LAST"), styleVar: "top"});
		
		// Process all HTML elements to modify
		for(var i = 0; i < resizeElements.length; i++)
		{
			if(resizeElements[i].element && resizeElements[i].element != null)
			{
				var element = resizeElements[i].element;
				var styleData = element.style[resizeElements[i].styleVar].replace("px", "");
				element.style[resizeElements[i].styleVar] = (parseInt(styleData) - stackedTabHeight) + "px";
			}
		}
	}
}


// Funktion des Dialogs IDD_PROJECTLIST_TABS zum Aktuali-
// sieren des Inhalts (Tabelle) des PROJECTLIST-Tabs
function refreshProjectlistTab()
{
    // Alle Eingabekontrollen des Dialogs deaktivieren
	disableInput();
    
	// Produkttabelle in eigenen IFrame (Dialog
    // IDD_PROJECTLIST) laden
    ekSubmit('IDC_REFRESH_PROJECTLISTTABLE', 'ProjectlistTableFrame');
}


// Funktion des Dialogs IDD_PROJECTLIST_TABS zum Aktuali-
// sieren des Inhalts (Tabelle) des PROJEKTLISTEN-
// Tabs, sofern der Projektlisten-Tab bereits beim
// Aufbau selektiert ist
function checkProjectlistTabTimeliness()
{
    var selectedTab = dialog.IDC_PROJECTTABCTRL.getSelected();
    
    if(selectedTab == "IDC_PROJECTPOSITIONS_TAB")
        refreshProjectlistTab();
}


/**
*	Routine used by project list dialog (IDD_PROJECTLIST_TABS)
*	in oder to setup a popup container and its underlying
*	IFrame. This popup gets displayed within inner IFrame of
*	project list dialog (IDD_PROJECTLIST) - which contains
*	just project list table - each time the process of inser-
*	ting a control item to project list is started. Using
*	Ajax requests this function requests content of popup
*	from server and transfers data entered by user. All pa-
*	rameters have to be passed within an anonymous object
*
*	@param action {String}: Keyword which defines which step
*			of the overall process should be performed
*				initialize - Start process by setting up
*					popup container and retrieving its con-
*					tent from server
*				addItem - Send all data required to insert
*					item to server as entered by user. Doing
*					so, the insertion takes place
*				abort - Hide popup and abort insertion pro-
*					cess by refusing data entered to its
*					input controls
*				
*
*	@return No data get returned by this routine
*/
function insertProjectlistControlItem(params)
{
	// Fetch current session id and the system's state informa-
	// tion to be able to send an Ajax request to server
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	
	var submitValues = {action: params.action};
	
	if(params.action == "addItem")
	{
		var controlItemData = {
			positionNr: $F("controlItemPositionNr"),
			controlCommands: [{
				target: "offerDoc",
				section: $F("controlItemSectionSelector"),
				commandType: $F("controlItemTypeSelector"),
				commandQuantity: $F("controlItemCommandQuantity")
			}]
		};
		
		submitValues.itemData = controlItemData;
		
	}
	// If user aborted setup of new control item, finalize
	// process by hiding popup element and underlying IFrame
	else if(params.action == "abort")
	{
		var popupElement = $("CONTROL_ITEM_SETTINGS_POPUP_CONTAINER");
		popupElement.iframeElement.style.display = "none";
		popupElement.style.visibility = "hidden";
		popupElement.innerHTML = "";
		return;
	}
	
	new Ajax.Request("ajax/insertProjectlistControlItem", {
		parameters:
		{
			'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&data=" + Object.toJSON(submitValues)
		},
		
		onSuccess: function(transport)
		{
			var responseData = transport.responseJSON;
			
			// Setup popup to query information required for creation of control
			// item from user
			if(responseData.action == "displayControlItemDataPopup")
			{
				var popupElement = $("CONTROL_ITEM_SETTINGS_POPUP_CONTAINER");
				
				if(!popupElement)
				{
					// Create DIV element and underlying IFrame which will carry
					// content of popup to create
					// Setup DIV element and integrate it into main form of dialog
					var popupElement = document.createElement("DIV");
					popupElement.id = "CONTROL_ITEM_SETTINGS_POPUP_CONTAINER";
					popupElement.className = "easykatStandard-controlItemPopupContainer";
					document.forms[0].appendChild(popupElement);
					
					// Setup underlying IFrame
					popupElement.iframeElement = document.forms[0].insertBefore(document.createElement("IFRAME"), popupElement);
					popupElement.iframeElement.frameBorder = 0;
					popupElement.iframeElement.className = "easykatStandard-controlItemPopupContainer";
					popupElement.iframeElement.src = "javascript: false";
					popupElement.iframeElement.style.zIndex = 10000;
					
					// Provide function checking content of all input fields the
					// popup contains which gets triggered by event observers in
					// order to control availability of button to add item
					popupElement.checkControlItemData = function(event)
					{
						if($F("controlItemPositionNr") != "" &&
						   $F("controlItemSectionSelector") != "" &&
						   $F("controlItemTypeSelector") != "" &&
						   $F("controlItemCommandQuantity") != "")
						{
							$("addItemSubmitButton").disabled = false;
						}
						else
							$("addItemSubmitButton").disabled = true;
					};
				}
				
				// Fill up popup container setup above with content received
				// from server and display it
				popupElement.innerHTML = responseData.popupContent;
				popupElement.iframeElement.style.display = "block";
				popupElement.style.visibility = "visible";
				
				// Setup event observer, so button to add item doesn't can't
				// be pushed until all relevant information are present
				$("controlItemPositionNr").observe("keyup", popupElement.checkControlItemData);
				$("controlItemSectionSelector").observe("change", popupElement.checkControlItemData);
				$("controlItemTypeSelector").observe("change", popupElement.checkControlItemData);
				$("controlItemCommandQuantity").observe("keyup", popupElement.checkControlItemData);
				
				parent.setIframeSize(popupElement, popupElement.iframeElement, "insertProjectlistControlItem");
			}
			else if(responseData.action == "getProjectListTable")
			{
				// Start final request to refresh project list table
				var submitPostString = "sessionid=" + sessionId + "&stateid=" + stateId + "&data={action: '" + responseData.action + "'}";
				
				var productTable = dialog["IDC_PROJLIST_TABLE"];
				productTable.update({"url": "ajax/insertProjectlistControlItem", "params": {'__eksubmit_values__' : submitPostString}});
				
				// Hide popup and underlying IFrame
				var popupElement = $("CONTROL_ITEM_SETTINGS_POPUP_CONTAINER");
				popupElement.iframeElement.style.display = "none";
				popupElement.style.visibility = "hidden";
				popupElement.innerHTML = "";
			}
		}
	});
}


// Funktion der Dialoge IDD_Document und IDD_Product zum
// Öffnen einer CAD-Zeichnung
function	openCADDrawing(filename)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/openCADDrawing?cadName="+filename);
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


/**
*	Function for initializing the document of an empty IFrame
*	HTML element which also cares about browser differences
*
*	@param iFrameId {String}: ID of the iFrame element whose
*			document should get initialized
*
*	@return iFrameDocument {Object}: The initialized document
*			of the iFrame element whose ID was passed or null,
*			if either the iFrame element with this ID doesn't
*			exist or its document could not be retrieved
*/
function initializeIFrameDocument(iFrameId)
{
	var iFrameElement = document.getElementById(iFrameId);
	var iFrameDocument = null;
	
	if(iFrameElement)
	{
		iFrameElement.allowTransparency = "true";
		
		// Firefox, Opera
		if(iFrameElement.contentDocument)
			iFrameDocument = iFrameElement.contentDocument;
		// Internet Explorer
		else if(iFrameElement.contentWindow)
			iFrameDocument = iFrameElement.contentWindow.document;
		// Others browsers ?
		else if(iFrameElement.document)
			iFrameDocument = iFrameElement.document;
		
		if(iFrameDocument)
		{
			iFrameDocument.open();
			iFrameDocument.close();
		}
	}
	
	return iFrameDocument;
}


/**
*	Function setting the background color of all dummy IFrames
*	of the EasyGuiXP product table to transparent, so back-
*	ground images can shine through, if desired. These dummy
*	IFrames get used to setup fixed rows and columns correct-
*	ly, if IE 5.x or 6.x is used. All parameters required to
*	perform the process get retrieved internally
*/
function setupIFrameTransparency()
{
	var currentProductTab = dialog.IDC_PRODUCT_TABS.getSelected();
	currentProductTab = currentProductTab.replace("PRODUCT_TAB", "");
	
	var tableRowHeaderIframeDocument = initializeIFrameDocument("PRODUCT_TABLE_" + currentProductTab + "_FL_IFRAME");
	var tableColHeaderIframeDocument = initializeIFrameDocument("PRODUCT_TABLE_" + currentProductTab + "_FC_IFRAME");
	
	if(tableRowHeaderIframeDocument)
		tableRowHeaderIframeDocument.body.style.backgroundColor = "transparent";
	if(tableColHeaderIframeDocument)
		tableRowHeaderIframeDocument.body.style.backgroundColor = "transparent";
}


// Funktion der Dialoge IDD_Document und IDD_Product zum
// Öffnen eines Dokuments mit nicht näher spetifiziertem
// Dateityp (z.B. Bild, Word-Dokument, ...)
function	openMiscDocument(filename)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/openMiscDocument?fileName="+filename);
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion der Dialoge IDD_PRODUCT und IDD_PROJECTLIST zum
// Ein- und Ausblenden der Details-Tabelle
function	toggleDetails(tableRowIndex, detailsIdent, productType, mode, artNr, treeIdent)
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/toggleDetails?tableRowIndex="+tableRowIndex+"&detailsId="+detailsIdent+"&productType="+productType+"&mode="+mode+"&artNr="+artNr+"&treeIdent="+treeIdent);
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion der Dialoge IDD_CFGSUMMARY, IDD_PROJECTLIST_TABS, IDD_DETAILS
// und IDD_OFFER zum Drucken eines RTF- oder PDF-Dokuments.
// Je nachdem, ob das System im Internet-Modus läuft und AJAX unterstützt
// wird, ändert sich der Funktionsablauf.
function	printDocument(event, format)
{
	// Alle Eingabekontrollen des Dialogs deaktivieren
	disableInput();
	
	// Wartemeldung anzeigen
	if (format == "PDF")
		displayPopupNotice("PDF_GENERATION");
	else if (format == "DOC")
		displayPopupNotice("DOC_GENERATION");
	
    // Das System läuft im Internet-Modus und AJAX
    // ist verfügbar
    if(operateInInternetMode() && Ajax.getTransport())
    {
        // Ergebnis-Objekt zeitverzögert empfangen,
		// um die Anzeige der Wartemeldung zu ermög-
		// lichen
		setTimeout(function() {
			var resultData = sendSyncRequest('printDocument', 'event='+event+'&format='+format+'&ajax=true').evalJSON();
			
			// Die "Bitte warten"-Meldung ausblenden und
            // alle Eingabekontrollen des Dialogs wieder
            // freigeben
			hidePopupNotice();
            enableInput();
			
			// Sofern ein Fehler während der Generierung
			// aufgetreten ist, das Systemfehler-Flag
			// setzen und die Funktion zur Ausgabe des
			// Fehlers aufrufen
			if(resultData.generationErrorOccurred)
			{
				$("SYSTEM_ERROR_OCCURRED").value = 1;
				checkSystemError();
				
				// If only merge process failed, open
				// generated document anyway
				if(resultData.isMergeError)
					window.open(resultData.documentFileUrl, "DocumentWindow", "width=800,height=600,resizable=yes");
			}
			else
			{
				// Dokument öffnen
				window.open(resultData.documentFileUrl, "DocumentWindow", "width=800,height=600,resizable=yes");
			}
		}, 5);
    }
    else
    {
		// Hidden-Feld zum Aufruf des Handlers zum
		// Starten des Dokument-Generierungsprozesses
		//anlegen
		createNewHiddenFormField("ek_ajax_url", "ajax/printDocument?format="+format+"&event="+event+"&ajax=false");
        ekSubmit("PRINT_DOCUMENT", 'isyiframe');
		
        // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
        // wie z.B. "dynrequest.js" in Konflikt zu geraten
        document.forms[0].removeChild($("ek_ajax_url"));
    }
}


/**
*	Handler for loading procedures triggered by a button or link
*	of the dialogs IDD_PROJECTLIST, IDD_CONFIG, IDD_OFFER. It car-
*	ries out the whole loading process including requesting deci-
*	sions, reacting on errors and displaying the new contents. Du-
*	ring the loading process it's called multiple times to process
*	all occurring events. These calls are all triggered by com-
*	mands generated by this routine itself, so they're irrelevant
*	for the initial call which is triggered by a button or link of
*	a certain dialog. All parameters have to be passed within an
*	anonymous object.
*
*	@param event {String}: Specifies which kind of data should be
*				loaded. The following keywords are allowed:
*					projectList: Load a saved projectlist
*					configuration: Load a saved configuration
*					offer: Load a saved offer
*	@param mode {String}: The step of the loading procedure to be
*				processed. Maybe one of the following keywords,
*				though only the initial two make sense. All others
*				will be used internally during the loading pro-
*				cess:
*					initalize - Ask the user a question before
*						the loading process is started (e.g.
*						how to deal with old data)
*					startLoading - Start the loading process di-
*						rectly without further user interaction
*					continue - Called by every confirmation dia-
*						log after the decision has been made. Used
*						to preprocess parameters for the next re-
*						quest, if necessary
*					checkVersionConfirm - If the version check
*						failed, ask the user how to go on now
*					checkIntegrityConfirm - If integrity problems
*						occurred during the data check, ask the
*						user how to proceed now
*					retrieveContent - Retrieve the prepared new
*						content from the server
*	@param lastCallServerData {Object}: Internal parameter which
*				is irrelevant for the initial call. It contains
*				all data the server sent as the response to the
*				last call of this routine. It can contain multiple
*				properties, but in most cases it's just used to
*				forward the message to display in a confirmation
*				dialog, if the user	has to make a decision
*	@param confirmData: Internal parameter which is irrelevant for
*				the initial call. Used to transfer the data the
*				user provided within a confirmation dialog to the
*				server. Contains different properties depending on
*				the contents of the confirmation dialog
*/
function loadData(params)
{
	disableInput({overrideParameter: true});
	
	// Fetch the current session id and the system's state informa-
	// tion to be able to send requests to the server
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	
	// Setup the object containing the data to transmit to the ser-
	// ver (except the sessionId and the stateId)
	var submitValues = {};
	
	// Flag controlling the transmission of a request, so nothing
	// is done anymore, if the process got aborted or an error
	// occurred
	var sendRequest = false;
	
	switch(params.mode)
	{
		// Pseudo-case which is called whenever a decision of a
		// confirmation has been made. Parameters set in the con-
		// firmation dialog are prepared for transmission to the
		// server
		case "continue":
			// Send a new request to the server which contains the
			// data the user has provided within the confirmation
			// dialog (mostly just the button he has clicked on)
			sendRequest = true;
			submitValues.parameter = params.confirmData;
		break;
		
		// Request a confirmation from the user before the loading
		// process starts
		case "initialize":
			switch(params.event)
			{
				case "projectList":
					displayConfirmationDialog({confirmationIdent: "projectListLoadRequest", calledFunctionName: "loadData", calledFunctionArguments: [{mode: "determineDataSource", event: params.event}]});
				break;
				
				case "offer":
					displayConfirmationDialog({confirmationIdent: "offerLoadRequest", calledFunctionName: "loadData", calledFunctionArguments: [{mode: "determineDataSource", event: params.event}]});
				break;
			}
		break;
		
		case "determineDataSource":
			// Initial request
			if(!params.lastCallServerData)
			{
				sendRequest = true;
				submitValues.determineDataSource = true;
				submitValues.loadingEvent = params.event;
				
				if(params.confirmData)
					submitValues.parameter = params.confirmData;
			}
			// Next request after data source has been determined
			// on server side
			else
			{
				var dataSource = params.lastCallServerData.dataSource;
				
				// If system is operating in internet mode and an
				// upload request has to be performed first
				if(dataSource == "webUpload")
					displayUploadPopup({loadingEvent: params.event});
				else if(dataSource == "localFileDialog")
					loadData({mode: "startLoading", event: params.event});
				else if(dataSource == "serverDataStore")
					selectStoredDataset({loadingEvent: params.event});
			}
		break;
		
		// Initiate the data loading process
		case "startLoading":
			sendRequest = true;
			submitValues.startLoadingProcess = true;
			
			if(params.confirmData)
				submitValues.parameter = params.confirmData;
			
			/*// Send out the data loading request
			new Ajax.Request("ajax/loadDataHandler", {
				parameters:
				{
					'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&data=" + Object.toJSON(submitValues)
				},
				
				onSuccess: function(transport)
				{
					var responseData = transport.responseJSON;
					
					if(responseData.situation != "abort")
						loadData({mode: responseData.situation, event: params.event});
					else
						enableInput();
					
					switch(responseData.status)
					{
						// If the loading was successful and no further
						// user interaction is necessary
						case "successful":
							switch(params.ident)
							{
								case "projectList":
									// Call this routine again with the corresponding
									// mode setting again to retrieve the new contents
									// of the projectlist table from the server
									loadData({mode: "fetchNewContent", event: params.event});
								break;
							}
						break;
						// If the user's decision is required because the version of the
						// content and the system don't match
						case "versionConfirmation":
							switch(params.ident)
							{
								case "projectList":
									// Delay the update of the dialog (table), request
									// the decision required for further processing and
									// call this routine again with the corresponding
									// mode setting after the decision has been made
									displayConfirmationDialog("loadContentVersionDifference", "loadData", [{mode: "versionConfirm", ident: params.ident, confirmMessage: responseData.confirmMessage}]);
								break;
							}
						break;
						// If the user's decision is required after the integrity has been
						// checked
						case "integrityConfirm":
							switch(params.ident)
							{
								case "projectList":
									// Delay the update of the dialog (table), request
									// the decision required for further processing and
									// call this routine again with the corresponding
									// mode setting after the decision has been made
									displayConfirmationDialog("projectListIntegrity", "loadData", [{mode: "integrityConfirm", ident: params.ident, confirmMessage: responseData.confirmMessage}]);
								break;
							}
						break;
						// If the loading process got aborted by the user (e.g. closing
						// the file chooser window), enable the screen controls again
						case "abort":
							// If a message was transmitted, display it as an error
							if(responseData.isError)
							{
								document.getElementById("SYSTEM_ERROR_OCCURRED").value = 1;
								checkSystemError();
							}
							
							enableInput();
						break;
						// If an incorrectible error occurred during the
						// loading process, abort it and retrieve the er-
						// ror message by a separate Ajax request
						case "error":
							document.getElementById("SYSTEM_ERROR_OCCURRED").value = 1;
							checkSystemError();
							enableInput();
						break;
						// If an unknown status is transmitted, abort the
						// loading process and just enable the screen con-
						// trols again
						default:
							enableInput();
						break;
					}
				}
			});*/
		break;
		
		// Send the user's decision concerning the processing of the inte-
		// grity check to the server. The corresponding confirmation mes-
		// sage is displayed, if the versions of the content and the sys-
		// tem don't match
		case "checkVersionConfirm":
			// Retrieve the confirmation message from the result of the
			// last call of this routine
			var message = params.lastCallServerData.confirmMessage;
			
			// Delay the update of the dialog (table), request
			// the decision required for further processing and
			// call this routine again with the corresponding
			// mode setting after the decision has been made
			displayConfirmationDialog({confirmationIdent: "loadContentVersionDifference", confirmationMessage: message, calledFunctionName: "loadData", calledFunctionArguments: [{mode: "continue", event: params.event}]});
			/*
			// If the user aborted the loading process
			if(params.confirmData.decision == "abort")
				enableInput();
			else
			{
				new Ajax.Request("ajax/loadDataHandler", {
					parameters:
					{
						'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&loadingEvent=" + params.ident + "&loadingStatus=integrity"
					},
					
					onSuccess: function(transport)
					{
						var responseData = transport.responseJSON;
						
						switch(params.ident)
						{
							case "projectList":
								// If no errors occurred during the integrity check,
								// load the projectlist's content
								if(responseData.status == "successful")
									loadData({mode: "fetchNewContent", ident: params.ident});
								else if(responseData.status == "integrityConfirm")
									displayConfirmationDialog("projectListIntegrity", "loadData", [{mode: "integrityConfirm", ident: params.ident, confirmMessage: responseData.confirmMessage}]);
								// If an incorrectible error occurred during the inte-
								// grity check, abort the loading process and retrieve
								// the error message by a separate Ajax request
								else if(responseData.status == "error")
								{
									document.getElementById("SYSTEM_ERROR_OCCURRED").value = 1;
									checkSystemError();
									enableInput();
								}
							break;
						}
					}
				});
			}*/
		break;
		
		// Send the user's decision concerning the continuing of the loa-
		// ding process to the server. The corresponding confirmation mes-
		// sage is displayed, if the one or more integrity errors occurred
		// during the integrity check of the content to load
		case "checkIntegrityConfirm":
			// Retrieve the confirmation message and the flags from the
			// result of the last call of this routine
			var message = params.lastCallServerData.confirmMessage;
			var updatePossible = params.lastCallServerData.updatePossible;
			
			// If the loading process has to get aborted due to errors
			// which occurred during the integrity check, disable the but-
			// ton triggering the continuation of the process
			var refuseLoading = params.lastCallServerData.refuseLoading;
			
			// Display different confirm buttons with specialized onclick
			// handler functions depending in the possibility to perform
			// an update or not
			var confirmationType = (updatePossible && !refuseLoading) ? "loadContentIntegrityUpdate" : "loadContentIntegrityNoUpdate";
			
			// Delay the update of the dialog (table), request
			// the decision required for further processing and
			// call this routine again with the corresponding
			// mode setting after the decision has been made
			displayConfirmationDialog({confirmationIdent: confirmationType, confirmationMessage: message, disableYesButton: refuseLoading, calledFunctionName: "loadData", calledFunctionArguments: [{mode: "continue", event: params.event}]});
			/*new Ajax.Request("ajax/loadDataHandler", {
				parameters:
				{
					'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&loadingEvent=" + params.ident + "&loadingStatus=processData&decision=" + params.confirmData.decision
				},
				
				onSuccess: function(transport)
				{
					var responseData = transport.responseJSON;
					
					switch(params.ident)
					{
						case "projectList":
							// Fetch the projectlist's updated content
							loadData({mode: "fetchNewContent", ident: params.ident});
						break;
					}
				}
			});*/
		break;
		
		// Retrieve the prepared new data from the server
		case "retrieveContent":
			switch(params.event)
			{
				case "projectList":
					// Refresh the table with the new projectlist data
					var productTable = this.frames['ProjectlistTableFrame'].dialog["IDC_PROJLIST_TABLE"];
					productTable.update({"url": "ajax/loadDataHandler", "params": {'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&data={}"}});
				break;
				
				case "configuration":
					// Focus the correct node of the product group
					// tree, if necessary
					var focusTreeNode = params.lastCallServerData.focusTreeNode;
					
					if(focusTreeNode)
					{
						if(focusTreeNode.toUpperCase() != "ROOT")
						{
							topEasykatFrame.dialog.IDC_TREE_CLASSES.focusItem(focusTreeNode);
							topEasykatFrame.dialog.IDC_TREE_CLASSES.setSelected(focusTreeNode);
						}
					}
					
					// Load the configuration dialog
					startRequest("ajax/ConfigInitialLoad");
				break;
				
				case "offer":
					// Fetch the data by a separate common HTML request, because it would be
					// too much effort to refresh all of the dialog's controls manually by
					// JavaScript commands
					ekSubmit('IDC_OFFER_LOAD');
				break;
			}
		break;
		
		case "abort":
		case "abortError":
			sendRequest = true;
			submitValues.parameter = {abortLoading: true};
			
			if(params.mode != "abortError")
				break;
		// If an error occurred, display the corresponding error message
		// and enable the screen controls again
		case "error":
		default:
			document.getElementById("SYSTEM_ERROR_OCCURRED").value = 1;
			checkSystemError();
			enableInput();
		break;
	}
	
	// Send out the request to continue the loading process, if permitted
	if(sendRequest)
	{
		new Ajax.Request("ajax/loadDataHandler", {
			parameters:
			{
				'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&data=" + Object.toJSON(submitValues)
			},
			
			onSuccess: function(transport)
			{
				var responseData = transport.responseJSON;
				
				// As long as the process didn't get aborted, continue it by
				// calling this routine again with the correct mode setting.
				// Doing so, forward all data returned by this call, too, so
				// they can be used by the routines (e.g. confirmation mes-
				// sage texts)
				if(responseData.situation != "abort")
					loadData({mode: responseData.situation, event: params.event, lastCallServerData: responseData});
				else
					enableInput();
			}
		});
	}
}


// Funktion des Dialogs IDD_PROJECTLIST zum Überprüfen der
// Verfügbarkeit des Buttons "Position ändern"
function checkPositionModify(event)
{
	// Retrieve the selected table row from the event
	// object
	var selectedRow = event.memo.value;
	
	// Wenn eine selektierte Zeile existiert
	if(selectedRow != "")
	{
		// Buttons aktivieren, denn sie könnten zuvor
		// deaktiviert worden sein
		parent.dialog["IDC_POSITION_COPY_BUT"].enable();
		parent.dialog["IDC_POSITION_DELETE_BUT"].enable();
		parent.dialog["IDC_PROJECT_REFRESH_BUT"].enable();
		
		// Typ des selektierten Produkts aus dem Hidden-
		// Field "projectlistProductTypes" laden
		var productTypes = eval("(" + $F("projectlistProductTypes") + ")");
		var curProductType = productTypes[selectedRow.substring(19)];
		
		// Sofern es ein konfigurierter Artikel ist,
		// aktiviere den Button "Position ändern"
		if(curProductType == "CONFIGURED")
			parent.dialog["IDC_POSITION_MODIFY_BUT"].enable();
		else if(curProductType != "UNCHANGEABLE" && curProductType != "NOMODIFY")
			parent.dialog["IDC_POSITION_MODIFY_BUT"].disable();
		else
		{
			parent.dialog["IDC_POSITION_MODIFY_BUT"].disable();
			// If it's not a catalog article,
			// disable the copy button, too
			if(curProductType != "CATALOG")
				parent.dialog["IDC_POSITION_COPY_BUT"].disable();
		}
	}
	// Wenn keine selektierte Zeile existiert
	// deaktiviere alle Buttons
	else
	{
		parent.dialog["IDC_POSITION_MODIFY_BUT"].disable();
		parent.dialog["IDC_POSITION_COPY_BUT"].disable();
		parent.dialog["IDC_POSITION_DELETE_BUT"].disable();
		parent.dialog["IDC_PROJECT_REFRESH_BUT"].disable();
	}
}


function saveData(params)
{
	if(params.getFilenameFromUser)
	{
		topEasykatFrame.saveRequestParameters = params;
		topEasykatFrame.saveRequestStartFrame = this;
		topEasykatFrame.requestSaveFilename();
	}
	else
	{
		var dialogData = Form.serialize(document.forms[0]);
		
		// Perform special scenario-dependent actions before starting request
		switch(params.scenario)
		{
			case "projectList":
				if(params.sendEmail && params.sendEmail == "true")
				{
					// Lock dialog's input controls and disable salutation combobox
					disableInput();
					$("*.PROJECT.SETTINGS.CLIENT.IDC_ANREDE_CUSTOMER").disabled = "true";
				}
			break;
			case "offer":
				if(params.sendEmail && params.sendEmail == "true")
				{
					// Lock dialog's input controls
					disableInput();
				}
			break;
		}
		
		// Start data saving request as Ajax request
		new Ajax.Request("ajax/saveDataHandler", {
			parameters:
			{
				'__eksubmit_values__' : dialogData + "&sessionid=" + $F("sessionid") + "&stateid=" + $F("stateid") + "&parameter=" + Object.toJSON(params)
			},
			
			onSuccess: function(transport)
			{
				var responseData = transport.responseJSON;
				
				if(responseData.errorOccurred)
				{
					topEasykatFrame.$("SYSTEM_ERROR_OCCURRED").value = 1;
					topEasykatFrame.checkSystemError();
				}
				else
				{
					if(responseData.sendEmail == "true")
						displayPopupNotice("EMAIL");
					else
					{
						if(!responseData.fileSavedOnServer)
						{
							if(responseData.scenario != "takeOverSettings")
							{
								if(responseData.internetMode)
									parent.displayDownloadPopup(responseData.downloadPopupData);
								else
								{
									if(responseData.scenario == "offerInterfaceXml")
										displayPopupNotice('EXPORT_OFFER_INTERFACE_XML');
								}
							}
							else
								displayPopupNotice('SAVE_SETTINGS');
						}
						else
							parent.displayPopupNotice('SERVER_STORAGE');
					}
				}
				
				if(responseData.sendEmail == "true")
				{
					enableInput();
					
					if(responseData.scenario == "projectList")
						$("*.PROJECT.SETTINGS.CLIENT.IDC_ANREDE_CUSTOMER").removeAttribute("disabled");
				}
				
				if(responseData.fileSavedOnServer)
					parent.hideSaveFilenameRequestPopup();
			}
		});
	}
}



// Funktion des Dialogs IDD_SETTINGS zum Speichern der
// persistenten Systemeinstellungen
function	saveSettings()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveSettings");
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_OFFER zum Speichern der
// Angebotsdaten
function	saveOffer()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveOffer?sendEmail=false");
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_PROJECTLIST_TABS zum Speichern
// der Projektliste
function	saveProject(params)
{
	if(params.displayFilenameRequest)
		topEasykatFrame.requestSaveFilename({scenario: 'projectList'});
	else
	{
		// Parameter des Handler-Aufrufs zusammenstellen und
		// als Hidden-Feld ins Formular einhängen
		var ajaxRequestParameter = "ajax/saveProject?sendEmail=false";
		
		if(params.userFilename)
			ajaxRequestParameter += "&userFilename=" + params.userFilename;
		
		createNewHiddenFormField("ek_ajax_url", ajaxRequestParameter);
		
		ekSubmit("", 'isyiframe');
		
		// Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
		// wie z.B. "dynrequest.js" in Konflikt zu geraten
		document.forms[0].removeChild($("ek_ajax_url"));
	}
}


// Funktion des Dialogs IDD_OFFER zum Versenden einer
// eMail an den Vertrieb, wenn der Konfigurator im
// kundenseitigen Modus läuft
function	sendRequestEmail()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveProject?sendEmail=true");
    
    // Dialog sperren und Anrede-Combobox auf disabled setzen
    disableInput();
    $("*.PROJECT.SETTINGS.CLIENT.IDC_ANREDE_CUSTOMER").disabled = "true";
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_CONFIG zum Speichern der
// aktuellen Konfiguration
function	saveConfiguration()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveConfiguration");
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_FAVORITELIST zum Speichern der
// Favoritenliste
function	saveFavList()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveFavList");
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_OFFER zum Generieren eines
// CSV-Dokuments mit den Angebotsdaten
function	createCSV()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/createCSV");
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_OFFER zum Versenden der
// Angebots-Daten an den Vertrieb unter Benutzung
// von MAPI-Mail
function	sendOfferEmail()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/saveOffer?sendEmail=true");
    
    // Dialog sperren
    disableInput();
    
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_OFFER zum Generieren eines
// XML-Dokuments mit den Angebotsdaten
function generateOfferInterfaceXML()
{
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/exportOfferInterfaceXml");
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Function which starts the take over of the price adjustment
// data currently being displayed in the secion 'calculation
// position' of the offer dialog to all positions included in
// the offer generation process (checkbox on the left side of
// the offer positions table is checked)
function applyOfferPricesToAllItems(event)
{
    // Fetch the data the server needs to assign the Ajax re-
    // quest to the correct user session
    var sessionId = $F("sessionid");
    var stateId = $F("stateid");
    
    // Set part of ID all dialogs controls which will be que-
    // ried now have in common
    var dialogControlsIdPrefix = "*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.POSITION.";
    
    // Retrieve the price adjustment information required by
    // the take over process
    var priceAdjustmentData = {
        hiddenPriceAdjustment: $(dialogControlsIdPrefix + "hiddenPriceAdjustment").value,
        hiddenPriceAdjustmentUnit: $(dialogControlsIdPrefix + "hiddenPriceAdjustmentUnit").value,
        visiblePriceAdjustment: $(dialogControlsIdPrefix + "visiblePriceAdjustment").value,
        visiblePriceAdjustmentUnit: $(dialogControlsIdPrefix + "visiblePriceAdjustmentUnit").value
    };
    
    new Ajax.Request("ajax/applyOfferPricesToAllItems", {
        parameters:
        {
            '__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&priceAdjustmentData=" + Object.toJSON(priceAdjustmentData)
        },
        
        onSuccess: function(transport)
        {
            var response = transport.responseJSON;
            
            if(response.updateDone == "true")
                calculate("full", "takeOverPriceAdjustment");
			else
				alert("Failure while applying price adjustments to all positions.");
        }
    });
}


// Funktion des Dialogs IDD_Offer zum Setzen der Angebotswährung
// in den entsprechenden Comboboxen
// Führt bei Währungsänderung oder bei Veränderung der Projekt-
// liste seit dem letzten Aufruf eine Neukalkulation durch
function	setOfferCurrency(combo)
{
    // Aktuell ausgewählte Währung speichern
    var currencyComboboxWidget    = dialog[combo];
    var curSelectedCurrencyId     = currencyComboboxWidget.getValue();
    var curSelectedCurrencyIdText = currencyComboboxWidget.getSelectedText();
    var lastCurrency              = document.getElementById("LAST_OFFER_CURRENCY");
    var recalculate = false;
    
    //alert("CurCurrency: " + curSelectedCurrencyId + " - LastCurrency: " + lastCurrency.value);
    
    // Bei Änderung der Währung eine Neukalkulation vornehmen
    if(lastCurrency.value != curSelectedCurrencyId)
        recalculate = true;
    
    // Zu änderne Comboboxen in einem Array angeben
    var targetComboboxes = new Array();
    targetComboboxes.push($('*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.OVERALL.adjustmentUnit'));
    targetComboboxes.push($('*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.POSITION.hiddenPriceAdjustmentUnit'));
    targetComboboxes.push($('*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.POSITION.visiblePriceAdjustmentUnit'));
    
    for(i = 0; i < targetComboboxes.length; i++)
    {
        // Die ID darf wegen der Kalkulation nicht verändert werden
       // targetComboboxes[i].options[1].value = curSelectedCurrencyId;
        targetComboboxes[i].options[1].text  = curSelectedCurrencyIdText;
    }
    
    // Alle Header-Zellen der Produkttabelle, die Währungs-
    // Kürzel beinhalten, aktualisieren (Währung ändern)
    var tableCellIndices = [5, 6, 8];
    var headerTable = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.OFFER_TABLE"].columnHeader.headerTable.rows[0];
    
    for(var i = 0; i < tableCellIndices.length; i++)
    {
        var resultData = headerTable.cells[tableCellIndices[i]].innerHTML.replace("[" + lastCurrency.value + "]", "[" + curSelectedCurrencyId + "]");
        headerTable.cells[tableCellIndices[i]].innerHTML = headerTable.cells[tableCellIndices[i]].innerHTML.replace("[" + lastCurrency.value + "]", "[" + curSelectedCurrencyId + "]");
    }
    
    // Währungshistorie aktualisieren
    lastCurrency.value = curSelectedCurrencyId;
    
    if(recalculate)
        calculate("full", "currencyChanged");
}


// Funktion des Dialogs IDD_Offer zur Selektierung
// oder Deselektierung aller Tabellenzeilen der
// Angebots-Tabelle
function	changeSelection()
{
    var offerTable = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.OFFER_TABLE"];
    var numRows    = offerTable.getRowCount();
	var selectAllRowsChecked = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.allTableRowsSelected"].element.checked;
	
    for(var i = 0; i < numRows; i++)
    {
        tableCell = offerTable.element.rows[i+1].cells[0];
        checkBox  = Element.getFirstChildByTagName(tableCell, 'input');
        checkBox.checked = selectAllRowsChecked;
    }
    
    // Hidden-Feld zum Aufruf des Handlers anlegen
    createNewHiddenFormField("ek_ajax_url", "ajax/changeSelection");
	
    ekSubmit("", 'isyiframe');
    
    // Ajax-URL-Feld löschen, um nicht mit anderen Ajax-Skripten
    // wie z.B. "dynrequest.js" in Konflikt zu geraten
    document.forms[0].removeChild($("ek_ajax_url"));
}


// Funktion des Dialogs IDD_Offer zur Anpassung des
// Selektierungsstatus der "Alle markieren"-Checkbox
// anhand der selektierten Tabellenzeilen
function	verifyCheckboxStatus()
{
    var offerTable = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.OFFER_TABLE"];
    var numRows    = offerTable.getRowCount();
    for(var i = 0; i < numRows; i++)
    {
        tableCell = offerTable.element.rows[i+1].cells[0];
        checkBox  = Element.getFirstChildByTagName(tableCell, 'input');
        if(!checkBox.checked)
        {
            dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.allTableRowsSelected"].element.checked = false;
            return;
        }
    }
    dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.allTableRowsSelected"].element.checked = true;
}


// Function used within calculation tab of IDD_OFFER which
// triggers calculation process on server side each time
// a relevant HTML input element got modified by user
// (e. g. visible or hidden price adjustment)
function calculate(mode, situation)
{
	// Setup global object used to handle event queueing
	// problems cause by triggering multiple events with
	// just one action. Example: leaving a changed combo-
	// box by clicking on a checkbox and modify its se-
	// lection state whereby two events get triggered
	if(!document.calcData)
	{
		document.calcData = {
			newEventOccurred: true,
			eventCheckSetup: false,
			mostComplexCalcMode: mode,
			mostComplexCalcSituation: situation
		};
	}
	
	// If one of the following scenarios are present:
	// - A certain HTML input field relevant for calculation 
	//   process got modified
	// - A different row of calculation data table got se-
	//   lected
	// - User clicked on a printing button within control
	//   buttons table to start offer document generation
	if(situation == "fieldDataChanged" || situation == "selectedRowChanged" || situation.indexOf("printOffer") != -1)
	{
		// Analyse parameters passed by each event and filter
		// out those who trigger the calculation task causing
		// most effort on server side. These parameters will
		// be passed to server as soon as no more events
		// occur for this user action
		// Effort hierarchy of parameter 'mode':
		// - full (highest)
		// - line (lowest)
		if(document.calcData.mostComplexCalcMode != "full")
			document.calcData.mostComplexCalcMode = mode;
		// Effort hierarchy of parameter 'situation':
		// - printOffer (highest)
		// - fieldDataChanged
		// - selectedRowChanged (lowest)
		if(situation.indexOf("printOffer") != -1)
			document.calcData.mostComplexCalcSituation = situation;
		else if(document.calcData.mostComplexCalcSituation.indexOf("printOffer") == -1)
		{
			if(document.calcData.mostComplexCalcSituation != "fieldDataChanged")
				document.calcData.mostComplexCalcSituation = situation;
		}
		
		// Set flag signalizing routine dealing with event
		// queueing, that another event occurred. This will de-
		// lay processing of request until a certain period of
		// time without any new event is reached
		document.calcData.newEventOccurred = true;
		
		// Setup event queueing handling routine
		if(!document.calcData.eventCheckSetup)
		{
			// Count the executions to stop processing, if a cer-
			// tain amount get exceeded to avoid endless loops
			var eventChecksPerformed = 0;
			
			// Set flag, that routine dealing with event queueing
			// has been setup
			document.calcData.eventCheckSetup = true;
			
			// Check periodically if another event called this
			// routine and delay processing of request until a
			// check process is performed without occurrance of
			// a new event
			var eventCheck = window.setInterval(function() {
				
				eventChecksPerformed++;
				
				// Start processing if no new event has called
				// this routine since last check or more than
				// twenty checks have been performed
				if(!document.calcData.newEventOccurred || eventChecksPerformed > 20)
				{
					window.clearInterval(eventCheck);
					
					calculate(document.calcData.mostComplexCalcMode, 'startRequest');
					
					// Reset data used by this routine which
					// includes the flag causing its reinstan-
					// tiation as next request gets triggered
					document.calcData.eventCheckSetup = false;
					document.calcData.mostComplexCalcMode = "";
					document.calcData.mostComplexCalcSituation = "";
				}
				// If a new event occurred since last check, re-
				// set flag signalizing it
				else
					document.calcData.newEventOccurred = false;
			}, 75);
		}
	}
	else
	{
		// Determine index of calculation table row currently
		// selected as well as number of rows it consists of
		var offerTableWidget = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.OFFER_TABLE"];
		var offerTableElement = offerTableWidget.element;
		var selectedTableRow = parseInt(offerTableWidget.getSelected().substring(15));
		var numTableRows = offerTableElement.rows.length;
		
		// Setup anonymous object passed to server which pro-
		// vides all information to process calculation task
		var calculationData = {
			offerTableRows: [],
			calculationMode: mode,
			situation: (situation == "startRequest") ? document.calcData.mostComplexCalcSituation : situation,
			selectedTableRow: selectedTableRow,
			lastSelectedTableRow: (situation != "initializeDialog") ? document.calcData.lastSelectedOfferTableRow : selectedTableRow,
			currency: $F("IDC_OFFER_CURRENCY"),
			offerOverall: {},
			offerCurrentPosition: {}
		};
		
		// Remember index of calculation table row which is
		// selected now in order to pass it as history value
		// during next request. Doing so, changes of selected
		// table row can be recognized and handles correspon-
		// dingly on server side
		document.calcData.lastSelectedOfferTableRow = selectedTableRow;
		
		if(situation != "initializeDialog")
		{
			// Retrieve modifiable calculation information of
			// each table row of calculation table
			for(var i = 1; i < numTableRows; i++)
			{
				// If table row doesn't represent a control item
				if(offerTableElement.rows[i].cells.length == 9)
				{
					calculationData.offerTableRows.push({
						quantity: offerTableElement.rows[i].cells[4].children[0].value,
						userCalcPrice: offerTableElement.rows[i].cells[8].children[0].value,
						isSelected: (offerTableElement.rows[i].cells[0].children[0].checked) ? "true" : "false"
					});
				}
				// If this table row represents a control item,
				// query only its selection status (checkbox
				// within first table cell) and set marker flag
				// which can be used on server side to recognize
				// thsi special product type
				else
				{
					calculationData.offerTableRows.push({
						isControlItem: true,
						isSelected: (offerTableElement.rows[i].cells[0].children[0].checked) ? "true" : "false"
					});
				}
			}
			
			// Retrieve the identifiers of all HTML input elements
			// representing calculation data (initialited by Java-
			// Script 'initFunctions.js'
			var calculationDataFields = eval($F("offerCalculationTabInputFields"));
			
			// Get values of all relevant HTML input elements, save
			// them within new anonymous objects and append these
			// data transferred to server with request
			for(var i = 0; i < calculationDataFields.length; i++)
			{
				var fieldId = calculationDataFields[i].id;
				var fieldInformation = fieldId.substring(fieldId.lastIndexOf(".") + 1, fieldId.length);
				
				// Check, if this input field contains calculation
				// information applied to row of calculation table
				// currently selected or to offer overall. Save
				// data to corresponding anonymous object
				if(fieldId.indexOf("DISPLAY.POSITION") != -1)
					calculationData.offerCurrentPosition[fieldInformation] = $F(fieldId);
				else if(fieldId.indexOf("DISPLAY.OVERALL") != -1)
					calculationData.offerOverall[fieldInformation] = $F(fieldId);
				// If it's an input field which can't be assigned
				// to certain part of offer data, save its value
				// as global property of response object
				else
				{
					var fieldValue = $F(fieldId);
					calculationData[fieldInformation] = (fieldValue && fieldValue != null) ? fieldValue : "";
				}
			}
		}
		
		
		// Fetch the data the server needs to assign the Ajax re-
		// quest to the correct user session
		var sessionId = $F("sessionid");
		var stateId = $F("stateid");
		
		new Ajax.Request("ajax/doCalculation", {
			parameters:
			{
				'__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&calculationData=" + Object.toJSON(calculationData)
			},
			
			onSuccess: function(transport)
			{
				// Retrieve data from server
				var dialogUpdateData = transport.responseJSON;
				
				// If values of HTML input elements representing calculation infor-
				// mation of calculation table row currently selected have to be
				// refreshed
				if(dialogUpdateData.selectedPosition)
				{
					// Iterate over all identifiers of HTML elements to update
					// which were provided by server
					for(var i = 0; i < dialogUpdateData.selectedPosition.inputFieldIds.length; i++)
					{
						var currentField = dialogUpdateData.selectedPosition.inputFieldIds[i];
						var dialogElement = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.POSITION." + currentField];
						
						if(!dialogUpdateData.selectedPosition.isControlItem)
						{
							// Text fields containing price information and notice
							// of position
							if(i < 7)
								dialogElement.setText(dialogUpdateData.selectedPosition[currentField]);
							// Comboboxes to choose unit of price adjustment
							else if(i < 9)
								dialogElement.setSelectedIndex(dialogUpdateData.selectedPosition[currentField]);
							// Checkbox toggling option status of position
							else
								dialogElement.element.checked = dialogUpdateData.selectedPosition[currentField];
							
							dialogElement.element.disabled = "";
							dialog["IDC_CALC_POSITION_PRICEADJ_APPLY_TO_ALL"].element.disabled = "";
						}
						else
						{
							// Text fields containing price information
							// of position
							if(i < 6)
								dialogElement.setText(dialogUpdateData.selectedPosition.zeroPrice);
							// Text field containing notice
							else if(i == 6)
								dialogElement.setText("");
							// Comboboxes to choose unit of price adjustment
							else if(i < 9)
								dialogElement.setSelectedIndex("Amount");
							// Checkbox toggling option status of position
							else
								dialogElement.element.checked = false;
							
							dialogElement.element.disabled = "disabled";
							dialog["IDC_CALC_POSITION_PRICEADJ_APPLY_TO_ALL"].element.disabled = "disabled";
						}
					}
				}
				
				// If values of HTML input elements representing calculation infor-
				// mation used for offer overall have to be refreshed
				if(dialogUpdateData.offerOverall)
				{
					dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.PRICE_FACTOR"].setText(dialogUpdateData.offerOverall.currentPriceFactor);
					
					// If at least one item is present within project list (other-
					// wise, handler returns only price factor, if it got changed)
					if(numTableRows > 1)
					{
						dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.OVERALL.listPrice"].setText(dialogUpdateData.offerOverall.overallListPrice);
						dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.OVERALL.adjustment"].setText(dialogUpdateData.offerOverall.overallAdjustment);
						dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.OVERALL.adjustmentUnit"].setSelectedIndex(dialogUpdateData.offerOverall.overallAdjustmentUnit);
						dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.OVERALL.calcPrice"].setText(dialogUpdateData.offerOverall.overallCalcPrice);
					}
				}
				
				// If calculation data displayed within each row of calculation
				// table have to be refreshed
				if(dialogUpdateData.offerTable)
				{
					for(var i = 0; i < dialogUpdateData.offerTable.length; i++)
					{
						var rowIndex = dialogUpdateData.offerTable[i].tableRowIndex;
						
						$("OFFERTABLE_UNITPRICE" + rowIndex).firstChild.nodeValue = dialogUpdateData.offerTable[i].productUnitPrice;
						$("OFFERTABLE_POSITIONPRICE" + rowIndex).firstChild.nodeValue = dialogUpdateData.offerTable[i].productPosPrice;
						dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.DISPLAY.TABLEDATA[" + rowIndex + "].calcPrice"].setText(dialogUpdateData.offerTable[i].productCalcPrice);
					};
				}
				
				// Alle Eingabefelder der Kalkulationstabelle
				// disabled schalten bis auf die der selek-
				// tierten Tabellenzeile. Beim Aktivieren des
				// Kalkulationspreis-Feldes auf den entspre-
				// chenden Parameter achten.
				// Set status of all modifiable input elements of whole
				// calculation table to disabled except of those con-
				// tained within table row currently selected
				for(var i = 1; i < numTableRows; i++)
				{
					var quantityDisabledStatus = true;
					var calcPriceDisabledStatus = true;
					
					// Check corresponding system parameter before
					// enabling edit field of table row currently
					// selected which contains calculated price
					if(i == (selectedTableRow + 1))
					{
						quantityDisabledStatus = false;
						
						if(!dialogUpdateData.noCalcPriceModification)
							calcPriceDisabledStatus = false;
					}
					
					// Check if current table row represents a con-
					// trol item and if so skip it because it does
					// not provide any calculation information
					if(offerTableElement.rows[i].cells.length != 9)
						continue;
					
					var quantityField = offerTableElement.rows[i].cells[4].children[0];
					var calcPriceField = offerTableElement.rows[i].cells[8].children[0];
					
					if(quantityField)
						quantityField.disabled = quantityDisabledStatus;
					
					if(calcPriceField)
						calcPriceField.disabled = calcPriceDisabledStatus;
				}
				
				// If user has clicked on a printing button of control but-
				// tons table, start its generation (this calculation re-
				// quest just had to be performed in order to handle cal-
				// culation data modified immediately before clicking on
				// printing button (so corresponding event couldn't get
				// processed, yet))
				if(dialogUpdateData.printOfferDocument)
					printDocument('PRINT_OFFER', dialogUpdateData.offerDocumentType);
				
				// Output error message, if a price adjustment limit (defined
				// by system parameters) has been exceeded and adaptions have
				// been rejected
				if(dialogUpdateData.priceAdjustmentErrorMessage)
					alert(dialogUpdateData.priceAdjustmentErrorMessage);
			}
		});
	}
}


function adaptOfferTableSelection(event)
{
	var adaptionRoutine = function() {
		var offerTableWidget = dialog["*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.CALC.OFFER_TABLE"];
		var offerTableElement = offerTableWidget.element;
		var selectedRowId = offerTableWidget.getSelected();
		var selectedRowNumber = parseInt(selectedRowId.substring(15)) + 1;
		var numTableRows = offerTableElement.rows.length
		
		// Alle Eingabefelder der Kalkulationstabelle
		// disabled schalten bis auf die der selek-
		// tierten Tabellenzeile. Beim Aktivieren des
		// Kalkulationspreis-Feldes auf den entspre-
		// chenden Parameter achten.
		for(var i = 1; i < numTableRows; i++)
		{
			var quantityDisabledStatus = true;
			var calcPriceDisabledStatus = true;
			
			if(i == selectedRowNumber)
			{
				quantityDisabledStatus = false;
				
				if(offerTableElement.getAttribute("modifyCalcPrice") != "1")
					calcPriceDisabledStatus = false;
			}
			
			// Check presence of edit field to set quantity first,
			// because it's not present for control items (these
			// special datasets don't contain any product informa-
			// tion) which must be skipped
			var quantityField = offerTableElement.rows[i].cells[4].children[0];
			var calcPriceField = offerTableElement.rows[i].cells[8].children[0];
			
			if(quantityField)
				quantityField.disabled = quantityDisabledStatus;
			
			if(calcPriceField)
				calcPriceField.disabled = calcPriceDisabledStatus;
		}
	}
	
	adaptionRoutine.defer();
}



// Funktion, die von allen Dialogen zur Ausgabe
// von Systemfehlern sowie allgemeinen Hinweisen
// verwendet wird. Die anzuzeigenden Daten werden
// in ein DIV-Element geladen, unter dem ein IFrame
// zur Überblendung von Comboboxen liegt. Beide
// Elemente werden erzeugt, sofern sie noch nicht
// existieren
function displayPopupNotice(noticeType)
{
    // Existenz des Popups abfragen
    var popupElement = topEasykatFrame.$("SYSTEMNOTICE_CONTAINER");
	
    // DIV-Element und IFrame für die Ausgabe 
    // der Daten anlegen
    if(!popupElement)
    {
        var topDocument = topEasykatFrame.document;
        
        // DIV-Element aufbauen und in den Haupt-
        // dialog integrieren
        popupElement = topDocument.createElement("DIV");
        popupElement.id = "SYSTEMNOTICE_CONTAINER";
        topDocument.body.appendChild(popupElement);
        
        // Unterlagernden IFrame aufbauen
        popupElement.iframeElement = topDocument.body.insertBefore(topDocument.createElement("IFRAME"), popupElement);
		popupElement.iframeElement.style.display = "none";
        popupElement.iframeElement.frameBorder = 0;
        popupElement.iframeElement.backgroundColor = "white";
		popupElement.iframeElement.src = "javascript: false";
        popupElement.iframeElement.style.zIndex = 10000;
        popupElement = $(popupElement);
    }
    
    // Anzuzeigende Daten und Meta-Informationen laden
	var content = sendSyncRequest("displayPopupNotice", "noticeType="+noticeType).evalJSON();
    
	if(content.noticeText != "")
	{
		// Style des Anzeige-Containers setzen
		popupElement.iframeElement.className = content.noticeStyle + "Container";
		popupElement.className = content.noticeStyle + "Container";
		
		// Meldung anzeigen und Ausblende-Timer setzen
		popupElement.innerHTML = "<table class=\"" + content.noticeStyle + "\"><tr><td><span>" + content.noticeText + "</span></td></tr></table>";
		popupElement.iframeElement.style.display = "block";
		popupElement.style.visibility = "visible";
		
		// Höhe des IFrame-Elements an die tatsächliche
		// Höhe der Meldungs-Tabelle anpassen
		popupElement.iframeElement.style.height = popupElement.childNodes[0].offsetHeight + "px";
		
		// Timeout für die Anzeige setzen (sofern nicht
		// auf 0 = nicht ausblenden gesetzt)
		if(content.displayTimeout > 0)
		{
			setTimeout("hidePopupNotice();", content.displayTimeout);
			popupElement.isPermanent = false;
		}
		else
			popupElement.isPermanent = true;
	}
}

// Funktion zum Ausblenden des Bereichs zur Anzeige
// von Systemfehler-Meldungen sowie allgemeinen
// Hinweisen
function hidePopupNotice()
{
	var popupElement = topEasykatFrame.$("SYSTEMNOTICE_CONTAINER");
    
    // Wenn das Popup-DIV-Element existiert und
    // nicht als permanent gekennzeichnet ist
	if(popupElement && !popupElement.isPermanent)
	{
		popupElement.iframeElement.style.display = 'none';
		popupElement.style.visibility = 'hidden';
	}
}

// Funktion, die von allen Dialogen zur Anzeige eines
// Popups zum Download einer Datei genutzt wird. Dazu
// wird ein DIV-Element mit einem unterliegenden
// IFrame erzeugt, welches die Popup-Daten enthält.
// Alle Argumente sind innerhalb eines anonymen Ob-
// jekts zu übergeben
//
// @param texts = Anonymes Objekt mit den anzuzeigen-
//                den Texten
//          buttonText: Text des Download-Buttons
//          linkText: Text des Schließen-Links
// @param fileUrl = relative URL der herunterzuladen-
//                  den Datei. Dabei sollten Alias-
//                  Namen verwendet werden
// @param downloadType = Art und Weise, auf die der
//                       Download erfolgen soll.
//          POPUP: Zeigt das Popup mit dem Button
//                 zum Download der Datei an
//          WINOPEN: Versucht, die Datei mittels
//                   window.open zum Herunterladen
//                   bzw. direkten Öffnen bereit-
//                   zustellen. Kritisch bei Pop-
//                   up-Blockern
function displayDownloadPopup(params)
{
    // Sofern der Download per window.open er-
    // folgen soll
    if(params.downloadType.toUpperCase() == "WINOPEN")
        window.open(params.fileUrl);
    // Sofern der Download per Popup durchge-
    // führt werden soll
    else
    {
        // Existenz des Popups abfragen
        var popupElement = topEasykatFrame.$("DOWNLOADPOPUP_CONTAINER");
        
        // DIV-Element und IFrame für die Ausgabe 
        // der Daten anlegen
        if(!popupElement)
        {
            var topDocument = topEasykatFrame.document;
            
            // DIV-Element aufbauen und in den Haupt-
            // dialog integrieren
            popupElement = topDocument.createElement("DIV");
            popupElement.id = "DOWNLOADPOPUP_CONTAINER";
            topDocument.body.appendChild(popupElement);
            
            // Unterlagernden IFrame aufbauen
            popupElement.iframeElement = topDocument.body.insertBefore(topDocument.createElement("IFRAME"), popupElement);
			popupElement.iframeElement.style.display = "none";
            popupElement.iframeElement.frameBorder = 0;
            popupElement.iframeElement.src = "javascript: false";
            popupElement.iframeElement.style.zIndex = 10000;
        }
        
        // Onclick-Handler zum Schließen des Popups beim
        // Anklicken des Buttons oder einer beliebigen
        // Stelle des Popup-DIV-Elements setzen. Dies
        // muss auf konventionelle Art geschehen, da der
        // IE den Handler sonst nach einem Neuaufbau des
        // RFrames (Dialogwechsel) nicht mehr startet
        popupElement.onclick = hideDownloadPopup;
        
        // Style des Anzeige-Containers und des DIV-Ele-
        // ments setzen
        popupElement.iframeElement.className = "easykatStandard-downloadPopupContainer";
        popupElement.iframeElement.style.border = "none";
        popupElement.iframeElement.style.padding = "4px";
        popupElement.className = "easykatStandard-downloadPopupContainer";
        
        // Meldung anzeigen und Ausblende-Timer setzen
        popupElement.innerHTML = "<div class='easykatStandard-downloadPopupButton'><input type='Button' value='" + params.texts.buttonText + "' onclick=\"parent.frames['isyiframe'].location.href = '" + params.fileUrl + "?download';\"/></div><div class='easykatStandard-downloadPopupCloseLink'>" + params.texts.linkText + "</div>";
        popupElement.iframeElement.style.display = "block";
        popupElement.style.visibility = "visible";
        
        setTimeout("hideDownloadPopup();", 60000);
    }
}

// Funktion zum Ausblenden eines Download-Popups
function hideDownloadPopup()
{
	var popupElement = topEasykatFrame.$("DOWNLOADPOPUP_CONTAINER");
	
	if(popupElement)
	{
		popupElement.iframeElement.style.display = 'none';
		popupElement.style.visibility = 'hidden';
	}
}

// Aufruf des zweiten UserExits, um die Vorschaudaten
// zum gerade durchgeführten Konfigurationsschritt zu
// laden. Die Funktion übernimmt auch die Verarbeitung
// und Visualisierung der zurückgelieferten Daten.
function getConfigPreviewData(params)
{
    // Benötigte Daten für den Request bereitstellen
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	var waitingNoticePresent = (params && params.userIsWaiting) ? 1 : 0;
	
    new Ajax.Request("ajax/getConfigPreviewData", {
        parameters:
        {
            '__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&waitingNoticePresent=" + waitingNoticePresent
        },
        
        onSuccess: function(transport)
        {
            try
            {
                var previewData = transport.responseJSON;
                
                // If the preview data to display changed or
				// the configuration is entered again by re-
				// turning from the summary dialog
                if(previewData && previewData.dataChanged)
                {
                    // If an image should be displayed
                    if(previewData.previewType == "image")
                    {
                        // Build up the image element
                        var previewImage = topEasykatFrame.document.createElement("img");
                        previewImage.id = "CFG_PREVIEW_IMAGE";
                        previewImage.src = previewData.content;
						
						if(previewData.clickHandler)
						{
							previewImage.style.cursor = "pointer";
							$(previewImage).observe("click", function(event) {
								eval(previewData.clickHandler);
							});
						}
						
                        // Replace the content of the table cell
                        // with the image
                        var previewTableCell = topEasykatFrame.$("CFG_PREVIEW_DATA_CELL");
                        previewTableCell.innerHTML = "";
                        Element.insert(previewTableCell, previewImage);
						
						// If some additional commands should be
						// performed for this refresh
						if(previewData.refreshAction)
							eval(previewData.refreshAction);
                    }
                    // If HTML code should be displayed
                    else if(previewData.previewType == "html")
                    {
                        // Replace the content of the table cell
                        // with the data returned
                        var previewTableCell = topEasykatFrame.$("CFG_PREVIEW_DATA_CELL");
                        
                        // If new content is present, replace the
                        // old data
                        if(previewData.content != "")
                        {
                            previewTableCell.innerHTML = "";
                            Element.insert(previewTableCell, previewData.content);
                        }
                        
                        // If a JavaScript function has to gene-
                        // rate of modify the content, call it
                        if(previewData.onload)
                            window[previewData.onload.func](previewData.onload.args);
                    }
                    
                    // Check, if the response provided the preview
                    // data or just the information to display
                    // during their generation
                    if(previewData.waitingInformation)
                    {
                        // Lock the dialog controls
                        disableInput({overrideParameter: true});
                        
                        // If the real preview data didn't get
                        // provided, trigger this function again
                        // with the waiting flag set
                        getConfigPreviewData({userIsWaiting: true});
                    }
                    else
                    {
                        // Enable the dialog controls again
                        enableInput();
                    }
                }
                else
                {
                    // Enable the dialog controls again
                    enableInput();
					return;
                }
                
                // If an error occurred, set the client side
                // error flag and trigger the handling rou-
                // tine to retrieve the error message
                if(previewData.errorOccurred)
                {
                    var configFrame = topEasykatFrame.frames['RFrame'];
                    
                    configFrame.$("SYSTEM_ERROR_OCCURRED").value = 1;
                    configFrame.checkSystemError();
                    
                    // Enable the dialog controls again
                    enableInput();
                }
            }
            catch(e)
            {
                alert("Fehler beim Laden der Vorschau-Daten.\nFehlermeldung: " + e.message);
				
				// Enable the dialog controls again
				enableInput();
            }
        }
    });
}


/**
*	Handler managing setup and update of popup dialog accessible by
*	the two buttons 'changeOverviewTableLayoutSettings' and 'change-
*	DetailsTableLayoutSettings' of layout tab of offer dialog. This
*	dialog provides certain parameters controlling content and lay-
*	out of some sections of printed offer document
*	
*	@param task {String}: Specifies the task which should be per-
*				formed by the handler during this call. These key-
*				worda are allowed:
*        			getPopupContent - Setup content of popup dialog
*						and display it. This includes the initiali-
*						zation of its container (DIV element), if
*						necessary
*					refreshValues - Update values resp. status of
*						all input controls the popup dialog contains.
*						Used to reset former state of these elements,
*						if the user has performed changes but aborted
*						their submission to server
*					saveValues - Transmit data of all input controls
*						to server, so they get taken over  by system
*	@param settingsSection {String}: Specifies the section of offer
*				document whose content and layout settings should get
*				adapted, so the corresponding parameters get provided
*				by popup dialog. These keywords are allowed:
*					overviewTable - Modify settings for overview ta-
*						ble of printed offer document
*					detailsTable - Modify settings for detailed in-
*						formation table of printed offer document
*/
function handleOfferLayoutSettings(params)
{
	var requestParameter = {};
	var popupContainer = topEasykatFrame.$("layoutSettingsContainer");
	
	// Retrieve content of popup dialog
	if(params.task == "getPopupContent")
	{
		var containerStyleClasses;
		var settingsSectionStyleClasses = {overviewTable: "overviewTableLayoutSettings", detailsTable: "detailsTableLayoutSettings"};
		var newContainerStyleClass = "easykatStandard-" + settingsSectionStyleClasses[params.settingsSection];
		
		// If container of popup dialog doesn't exist, yet (initial
		// call of this handler since main dialog has been refreshed)
		if(!popupContainer)
		{
			var topDocument = topEasykatFrame.document;
			
			// Setup div container of popup to display as part of main
			// dialog, so it won't get covered by overlay preventing
			// further user inputs which is also placed there and has
			// a high zIndex value. Keep it hidden until content has
			// been loaded by Ajax request
			popupContainer = topDocument.createElement("DIV");
			popupContainer.id = "layoutSettingsContainer";
			popupContainer.style.display = "none";
			containerStyleClasses = ["easykatStandard-offerLayoutSettingsPopupContainer"];
			topDocument.body.appendChild(popupContainer);
			popupContainer = Element.extend(popupContainer);
		}
		// If container is already present, retrieve its CSS classes
		// in order to find out, which settings section has been loa-
		// ded at last
		else
			containerStyleClasses = $w(popupContainer.className);
		
		// Only reload whole content of popup, if it's either not
		// initialized, yet, or another settings section than dis-
		// played at last should be displayed
		if(containerStyleClasses.length < 2 || containerStyleClasses[1] != newContainerStyleClass)
			containerStyleClasses[1] = newContainerStyleClass;
		// Update values of input controls only (used to reset them)
		else
			params.task = "refreshValues";
		
		requestParameter = params;
		disableInput();
	}
	// Transmit changes the user performed to server
	else if(params.task == "saveValues")
	{
		// Forward parameters passed to this handler to server, so
		// the same action gets performed there, too. Afterwards,
		// retrieve data of all input controls (edit fields and
		// checkboxes) and add them to information sent to server
		requestParameter = params;
		var inputElements = popupContainer.select('input');
		
		for(var i = 0; i < inputElements.length; i++)
		{
			if(inputElements[i].type == "text")
			{
				// Add disabled edit field values to respnose data,
				// too, if information of overview table gets
				// handled. This has to be done because they all
				// get saved on server side
				if(params.settingsSection == "overviewTable" || !inputElements[i].disabled)
					requestParameter[inputElements[i].id] = inputElements[i].value;
			}
			else
				requestParameter[inputElements[i].id] = inputElements[i].checked;
		}
	}
	// Request setup of default values for layout settings on
	// server side
	else if(params.task == "setupParameterDefaults")
	{
		// Just forward parameters passed to this handler to
		// server, so the same action gets performed there, too
		requestParameter = params;
	}
	
	// Exchange parameters controlling processing of request as
	// well as, if applicable, data retrieved from input controls
	// of popup dialog with server by Ajax request
	new Ajax.Request("ajax/handleOfferLayoutSettings", {
		parameters:
        {
            '__eksubmit_values__' : "sessionid=" + $F("sessionid") + "&stateid=" + $F("stateid") + "&parameter=" + Object.toJSON(requestParameter)
        },
		
		onSuccess: function(transport)
		{
			// Retrieve and extract server response (JSON object)
			var responseData = transport.responseJSON;
			
			// If request was handled correctly
			if(responseData.successful)
			{
				// If content of popup dialog has to be loaded and
				// got retrieved from server, insert it to container
				// element, set its CSS style classes and show it
				if(params.task == "getPopupContent" && responseData.popupData)
				{
					popupContainer.innerHTML = responseData.popupData;
					popupContainer.className = containerStyleClasses[0] + " " + containerStyleClasses[1];
					
					if(params.settingsSection == "detailsTable")
					{
						var checkboxes = popupContainer.select('input[type="checkbox"]');
						
						var adaptEditFieldChangeability = function(event) {
							var clickedCheckbox = (event.memo) ? event.memo.checkbox : Event.element(event);
							var editFieldId = clickedCheckbox.id.replace("Active", "Width");
							
							var columnWidthEditField = popupContainer.select('input[id="' + editFieldId + '"]')[0];
							columnWidthEditField.disabled = !clickedCheckbox.checked;
						};
						
						for(var i = 0; i < checkboxes.length; i++)
						{
							if(!checkboxes[i].disabled)
							{
								checkboxes[i].observe("click", adaptEditFieldChangeability);
								checkboxes[i].observe("adapt:EditState", adaptEditFieldChangeability);
								checkboxes[i].fire('adapt:EditState', {checkbox: checkboxes[i]});
							}
						}
					}
					
					popupContainer.style.display = "";
				}
				// If only values of all input controls of popup
				// dialog have to be refreshed (reset to further state)
				else if(params.task == "refreshValues")
				{
					// Retrieve all input controls the popup dialog
					// contains and change their values to those
					// provided by server
					var inputElements = popupContainer.select('input[type="text"]');
					
					for(var i = 0; i < inputElements.length; i++)
					{
						var editFieldId = inputElements[i].id;
						
						inputElements[i].value = responseData[editFieldId];
						
						/*if(params.settingsSection == "detailsTable")
						{
							var checkboxNotChecked = (responseData[editFieldId.replace("Width", "Active")] == "1") ? false : true;
							inputElements[i].disabled = checkboxNotChecked;
						}*/
					}
					
					if(params.settingsSection == "detailsTable")
					{
						var inputElements = popupContainer.select('input[type="checkbox"]');
						
						for(var i = 0; i < inputElements.length; i++)
						{
							inputElements[i].checked = (responseData[inputElements[i].id] == 1) ? "checked" : "";
							inputElements[i].fire('adapt:EditState', {checkbox: inputElements[i]});
						}
					}
					
					popupContainer.show();
				}
				// If modified settings got transferred to server by
				// this request, hide popup dialog and permit user to
				// access main dialog again (remove overlay)
				else if(params.task == "saveValues")
				{
					popupContainer.hide();
					enableInput();
				}
			}
			// If an error occurred while processing this request on
			// server side:
			// - hide popup dialog, if displayed
			// - release main dialog again
			// - set error flag to mark error status on client side, too
			// - call handler loading error message from server and
			//   displaying it
			else
			{
				if(popupContainer)
					popupContainer.hide();
				
				enableInput();
				$("SYSTEM_ERROR_OCCURRED").value = 1;
				checkSystemError();
			}
		}
	});
}


/**
*	Handler used within offer dialog which informs server about
*	change of offer languge (combobox item in basic data tab). It
*	submits content of certain language-dependent input fields to
*	server and updates it with new default values. But of course
*	all elements whose data have already been modified by user
*	won't be overwritten with default values retrieved in new offer
*	language
*	
*	@param event {object}: Object representing the event triggering
*			this handler. It's passed by corresponding observer each
*			time language combobox gets changed. The new offer lan-
*			guage is loaded from the target element (language combo-
*			box) of this event object. If this parameter is missing,
*			handler will retrieve HTML element of language combobox
*			on the base of its ID and gets its selected entry this way
*/
function performOfferLanguageChange(event)
{
	// Retrieve ID of new offer language which has been chosen by user
	var newLanguage = (typeof event != "object") ? $F("IDC_OFFER_LANGUAGE") : Event.element(event).getValue();
	
	// Setup array containing HTML element objects of all relevant
	// (this means language dependent) input fields of offer dialog
	var relevantDialogControls = [$("IDC_OFFER_REFERENCE"), $("IDC_OFFER_NOTICE"), $("*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.IDC_OFFER_CTRL_PARAM")];
	
	// Retrieve content of input elements and convert data into a JSON
	// string. In order to submit information as GET parameter, it's
	// necessary to replace all occurrences of the characters with
	// special meaning (& and =) with unique alternative expressions
	var dialogControlsInfo = Object.toJSON(Form.serializeElements(relevantDialogControls, {hash: true})).replace(/&/g, "@@@").replace(/=/g, ":::");
	
	// If some data to submit are present
	if(dialogControlsInfo)
	{
		// Inform server about change of offer language, so it can
		// provide new data for all language dependent dialog ele-
		// ments. By doing so, include current contents of these
		// elements in order to save them on server side and allow
		// decision if update with new default values can be per-
		// formed or not due to modifications by user
		new Ajax.Request("ajax/performOfferLanguageChange", {
			parameters:
			{
				'__eksubmit_values__' : "sessionid=" + $F("sessionid") + "&stateid=" + $F("stateid") + "&newLanguage=" + newLanguage + "&dialogControlsInfo=" + dialogControlsInfo
			},
			
			onSuccess: function(transport)
			{
				// Load data passed by server and update all
				// relevant dialog elements with default data
				// provided in new offer language
				var responseData = transport.responseJSON;
				
				for(var currentControl in responseData)
				{
					switch(currentControl)
					{
						case "IDC_OFFER_REFERENCE":
						case "IDC_OFFER_NOTICE":
							$(currentControl).setValue(responseData[currentControl]);
						break;
						case "*.DLGDATA.DLGVARS.EASYKATLIGHT.IDD_OFFER.IDC_OFFER_CTRL_PARAM":
							var controlParamCombobox = $(currentControl);
							var comboboxOptionData = responseData[currentControl];
							
							for(var i = 0; i < comboboxOptionData.length; i++)
							{
								controlParamCombobox.options[i].value = comboboxOptionData[i].submitValue;
								controlParamCombobox.options[i].text = comboboxOptionData[i].text;
							}
						break;
					}
				}
			}
		});
	}
};



function toggleConfigScrollingStrategy(clickedButton)
{
	var newStrategy = clickedButton.id.substring(14);
	
	// Inform server about new scrolling strategy using an Ajax request
	new Ajax.Request("ajax/setCfgScrollingStrategy", {
		parameters:
        {
            '__eksubmit_values__' : "sessionid=" + $F("sessionid") + "&stateid=" + $F("stateid") + "&scrollingStrategy=" + newStrategy
        },
		
		onSuccess: function(transport)
		{
			var responseData = transport.responseJSON;
			
			if(!responseData.successful)
				alert("Error changing srcolling mode !");
			else
				$("CFG_SCROLLING_CURRENT_STRATEGY").innerHTML = responseData.strategyApplied;
		}
	});
}


function autoResizePreviewWindow(previewImageWidth, previewImageHeight)
{
	var previewWindow;
	var numCalls = 0;
	
	var findWindowFunction = window.setInterval(function() {
		previewWindow = EasyKat.Configuration.preview.zoomImageWindow;
		numCalls++;
		
		if(previewWindow)
		{
			window.clearInterval(findWindowFunction);
			
			if(is.ie)
				previewWindow.resizeTo(previewImageWidth + 46, previewImageHeight + 66);
			else
				previewWindow.resizeTo(previewImageWidth + 30, previewImageHeight + 85);
		}
		else if(numCalls > 10)
			window.clearInterval(findWindowFunction);
	}, 25);
}


// Call pickup service for retrieving data objects
// prepared on server side in corresponding store
// section. The parameter 'params' can be omitted
// except during initialization
function PickupService_Request(params)
{
	// Provide data necessary to perform the request
	var sessionId = $F("sessionid");
	var stateId = $F("stateid");
	
	if(!params)
		var params = {requestCmd: "", validTasks: ""};
	
    new Ajax.Request("ajax/PickupService_Request", {
        parameters:
        {
            '__eksubmit_values__' : "sessionid=" + sessionId + "&stateid=" + stateId + "&requestCmd=" + params.requestCmd + "&validTasks=" + params.validTasks
        },
        
        onSuccess: function(transport)
        {
            try
            {
				var pickupData = transport.responseJSON;
				var sTaskName;
                var idx;
                var jdx;
				
				// Trigger callback function of each task which
				// requested data from the pickup service
				for (idx = 0; idx < pickupData.count; ++idx)
				{
					sTaskName = pickupData.content[idx].TASKNAME
					for (jdx = 0; jdx < topEasykatFrame.length; ++jdx)
					{
						if(sTaskName == topEasykatFrame.pupnames[jdx])
							topEasykatFrame.pupfktn[jdx](pickupData.content[idx]);
					}
				}
				
                // If an error occurred, set the client side
                // error flag and trigger the handling rou-
                // tine to retrieve the error message
                if(pickupData.errorOccurred)
                {
                    var configFrame = this.frames['RFrame'];
                    
                    configFrame.$("SYSTEM_ERROR_OCCURRED").value = 1;
                    configFrame.checkSystemError();
                    
                    // Enable the dialog controls again
                    enableInput();
                }
            }
            catch(e)
            {
                alert("Error while processing pickup services.\nError message: " + e.message);
				
				// Enable the dialog controls again
				enableInput();
            }
        },
		onFailure: function( transport ) {
			alert("Communication error while processing pickup services.");
		}
    });
}
