var tacos_global = this;

function tacos_undef(name, obj)
{
    if (!obj) { obj = tacos_global; }
    return (typeof obj[name] == "undefined");
}

if (tacos_undef("tacosConfig")) {
	var tacosConfig = {};
	tacosConfig.popupWhenException = true;
}
if (!tacosConfig.defaultExceptionConsoleId)
	tacosConfig.defaultExceptionConsoleId = "exceptionId";

//
// Enables wait cursor on requests
//
var BoilerPlate = new Object();
BoilerPlate.Cursor = {
    setCursor: function(cursor)
    {
        BoilerPlate.Cursor.resetCursor();
        document.body.style.cursor = cursor;
    },

    setElementCursor: function(element, cursor)
    {
        if (!element || typeof element.style == "undefined")
            return;
		
        if (!this.cursorQueue) {
            this.cursorQueue = [];
        }
        this.cursorQueue.push(element);
        element.style.cursor = cursor;
    },

    resetCursor: function()
    {
        document.body.style.cursor = "auto";
        if (this.cursorQueue) {
            for (var i = 0; i < this.cursorQueue.length; i++) {
                if (this.cursorQueue[i]) {
                    this.cursorQueue[i].style.cursor = "auto";
                }
            }

            this.cursorQueue = null;
        }
    }
};

//
// Core tacos library
//
var tacos = new Object();
tacos.forms = {};
tacos.processInFlight = false;
tacos.requestsInFlight = 0;

tacos.isServingRequests = function() {
	return (tacos.requestsInFlight > 0);
}

tacos.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
}

tacos.getContentAsStringOld = function(elem) {
	var returnVal = '';

	if (typeof elem == 'string') {
		returnVal = elem;
	} else if (typeof elem == 'undefined') {
		returnVal = elem;
	} else if (elem.innerText) {
		returnVal = elem.innerText;
	} else {
		var cs = elem.childNodes;
		for (var i=0; i < cs.length; i++)
			switch (cs[i].nodeType) {
				case 1: //ELEMENT NODE
					returnVal += XBinnerText(cs[i]);
					break;
				case 3: //TEXT NODE
					returnVal += cs[i].nodeValue;
					break;
			}
	}
	return returnVal;
}

tacos.getContentAsString = function(parentNode)
{
    if (tacosConfig.useGenericXmlSerializer)
        return tacos._getContentAsStringGeneric(parentNode);
    
    if (typeof parentNode.xml != "undefined")
		return tacos._getContentAsStringIE(parentNode);
	else if (typeof XMLSerializer != "undefined" )
		return tacos._getContentAsStringMozilla(parentNode);
	else
		return tacos._getContentAsStringGeneric(parentNode);
}

tacos._getContentAsStringIE = function(parentNode)
{
    var contentStr = "";
    for (var i = 0; i < parentNode.childNodes.length; i++)
        contentStr += parentNode.childNodes[i].xml;
    return contentStr;
}

tacos._getContentAsStringMozilla = function(parentNode)
{
    var xmlSerializer = new XMLSerializer();
    var contentStr = "";
    for (var i = 0; i < parentNode.childNodes.length; i++) {
        contentStr += xmlSerializer.serializeToString(parentNode.childNodes[i]);
        if (contentStr == "undefined") {
	        return tacos._getContentAsStringGeneric(parentNode);	        
	    }
    }
    // fix textareas for mozilla
    contentStr = tacos.fixTextarea(contentStr);
    return contentStr;
}

tacos._getContentAsStringGeneric = function(node){
	var _result = "";
	if (node == null) { return _result; }
	for (var i = 0; i < node.childNodes.length; i++) {
		var thisNode = node.childNodes[i];
		switch (thisNode.nodeType) {
			case 1: // ELEMENT_NODE
			case 5: // ENTITY_REFERENCE_NODE
				_result += tacos._getElementAsStringGeneric(thisNode);
				break;
			case 3: // TEXT_NODE
			case 2: // ATTRIBUTE_NODE
			case 4: // CDATA_SECTION_NODE
				_result += thisNode.nodeValue;
				break;
			default:
				break;
		}
	}
	return _result;	
}

tacos._getElementAsStringGeneric = function(thisNode){
	var _result = "";
	if (thisNode == null) { return _result; }
	// start tag
	_result += '<' + thisNode.nodeName;
	// add attributes
	if (thisNode.attributes && thisNode.attributes.length>0) {
		for (var i = 0; i < thisNode.attributes.length; i++) {
			_result += " " + thisNode.attributes[i].name 
				+ "=\"" + thisNode.attributes[i].value + "\"";	
		}
	}
	// close start tag
	_result += '>';
	// content of tag
	_result += tacos._getContentAsStringGeneric(thisNode);
	// end tag
	_result += '</' + thisNode.nodeName + '>';
	return _result;
}

//Regexp matcher for javascript blocks in html content
tacos.TextareaMatcher = '<textarea(.*?)/>';

tacos.fixTextarea = function(contentStr)
{
	var match = new RegExp(tacos.TextareaMatcher);
	contentStr = contentStr.replace(match, "<textarea$1></textarea>");
	// TODO: use while instead of recursion?
	if (contentStr.match(match))
		return tacos.fixTextarea(contentStr);
	else
		return contentStr;
}

//
// Retrieves text from an XML node and children nodes.
//
tacos._textFromXML = function(node){
	var toxml = "";
	if (node.nodeType==3) {
		toxml += node.nodeValue;
	}
	if (node.childNodes) {
		for (var i=0; i<node.childNodes.length; i++) {
			toxml += tacos._textFromXML(node.childNodes[i]);
		}
	}
	return toxml;
}

//
// Dojo's IframeIO transport is buggy on IE when the request is multipart.
// In that case, the response xml is hidden in text nodes. This function 
// tries to get the response text and convert it to xml.
//
tacos._fixIframeDataForIE = function(data) {
	dojo.debug("Try IE fix for iframe reponse.");
	var content = tacos._textFromXML(data);
	// remove doctype and first -
	var pos1 = content.indexOf("<!DOCTYPE");
	var pos2 = content.indexOf("- ");
	if (pos1>=0 && pos2>pos1) {
		content = /*content.substring(0,pos1-1) + */content.substring(pos2+1);
		try {
	    	var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
	    	xmlDoc.async = false;
	    	xmlDoc.loadXML(content);
	    	data = xmlDoc;
    	}
    	catch (e) {}		
	}
	return data;
}

//
// Checks for existance of proper response and attempts to do default
// error handling if the response looks invalid.
//
tacos.loadDojoResponse = function(type, data, request, kwArgs)
{
    var response = data.getElementsByTagName("ajax-response");
    // Handle errors..if no ajax-response nodes but there is data
    // then it is probably a server redirect or exception page
    if (response == null || response.length < 1) {
        tacos.responseComplete(data);
        dojo.debug("Received response, but had no elements of type ajax-response or the xml returned is not well-formed");
        dojo.debug("Response: " + request.responseText);
        if (tacosConfig.debugAjaxResponseError) {
	        setTimeout(function() {
	          BoilerPlate.Cursor.resetCursor();
	          var showData=dojo.html.renderedTextContent(data);	          
	          document.close();document.open();                   
	          document.writeln("<b>The response is either invalid xml or was not generated by ajaxdirectservice</b><br/>");
	          document.writeln("<textarea rows='30' cols='120'>");
	          document.writeln(showData);
	          document.writeln("</textarea><br/>");
	          document.close();
	        }, 20);
        }
        return false;
    }
	
    if (kwArgs["processScripts"]) {
      var remNodes = new Array();
        var responseNodes = response[0].childNodes;
        //If js includes exist, need to evaluate them first
        for (var i = 0; i < responseNodes.length; i++) {
            var responseElement = responseNodes[i];
			
            // only process nodes of type element.....
            if (responseElement.nodeType != 1)
                continue;
			
            var responseId = responseElement.getAttribute("id");
            var responseType = responseElement.getAttribute("type");
            dojo.debug("preProcessScripts id:" + responseId);
            if (responseId == "jsincludes" || responseId == "preprocess") {
                var incontent = tacos.getContentAsString(responseElement);
                tacos.processScripts(incontent, false);
				
                remNodes.push(responseElement);
            }
        }
		
        //remove nodes already processed
        for (var i = 0; i < remNodes.length; i++) {
          dojo.dom.removeNode(remNodes[i]);
        }
    }
	
    tacos.processAjaxResponse(response[0].childNodes, kwArgs);
    return true;
}

dojo.require("dojo.lfx.html");

//
// Main entry point for ajax-response processing of a response
// after it has been determined to be valid and complete
//
tacos.processAjaxResponse = function (xmlResponseElements, kwArgs)
{
	/* Added by rpack on 9/2/2006 */
	var updatedIDs = [];
	/* End add by rpack */
    for (var i = 0; i < xmlResponseElements.length; i++) {
        var responseElement = xmlResponseElements[i];
        // only process nodes of type element.....
        if (responseElement.nodeType != 1)
            continue;
        var responseType = responseElement.getAttribute("type");
        var responseId = responseElement.getAttribute("id");
        /* Added by rpack on 9/2/2006 */
        updatedIDs.push(responseId);
        dojo.debug("Added responseId: " +responseId+ " to updateID list.");
        /* End add by rpack */
        if (responseType == "element" && responseId != "scriptblock"
        		&& responseId != "postprocess") {
			
            dojo.debug("processAjaxResponse responseId:" + responseId);
            var cancelProcessing = false;
            //Call optional updateObject beforeAjaxUpdate
            if (kwArgs["updateObject"]
                    && typeof kwArgs["updateObject"].beforeAjaxUpdate != "undefined")
                cancelProcessing = kwArgs["updateObject"].beforeAjaxUpdate(responseElement, responseId);
			
            //replace element contents
            if (!cancelProcessing) {
                tacos.loadElement(responseElement, responseId, kwArgs);
            }
        } else if (responseType == "statustext") {
            //if they specified their own status update area
            if (kwArgs["statusElement"]) {
                var statusElement = document.getElementById(kwArgs["statusElement"]);
                if (!statusElement) continue;
                statusElement.innerHTML = tacos.getContentAsString(responseElement);
                //animation
                dojo.lfx.html.fadeShow(statusElement, 100, null, function()
                {
                    setTimeout(function()
                    { 
                        dojo.lfx.html.fadeHide(statusElement, 400).play();
                    }, 2000);
                }).play();
            }
        } else if (responseType == "exception") {
            tacos.handleException(responseElement);
            dojo.debug("after handle exception!");
        }
    }
	
	//postprocessing scripts
	if (kwArgs["processScripts"]) {
      var remNodes = new Array();
        //If js includes exist, need to evaluate them first
        for (var i = 0; i < xmlResponseElements.length; i++) {
            var responseElement = xmlResponseElements[i];
			
            // only process nodes of type element.....
            if (responseElement.nodeType != 1)
                continue;
			
            var responseId = responseElement.getAttribute("id");
            var responseType = responseElement.getAttribute("type");
            dojo.debug("postProcessScripts id:" + responseId);
            if (responseId == "postprocess") {
                var incontent = tacos.getContentAsString(responseElement);
                tacos.processScripts(incontent, true);
				
                remNodes.push(responseElement);
            }
        }
		
        //remove nodes already processed
        for (var i = 0; i < remNodes.length; i++) {
          	dojo.dom.removeNode(remNodes[i]);
        }
    }
	
	tacos._notifyListenerOnResponseComplete(kwArgs["updateObject"], xmlResponseElements);	
    tacos.responseComplete(xmlResponseElements);
	/* Added by rpack 9/2/2006 */
	/* Publish the array of updated node id's to the XHRComplete topic.
	 * This allows Dojo widgets to connect to an event in order to update
	 * themselves when their underlying dom has changed. The updateIDs array
	 * is created when the responseId is read from the response.
	 */
	dojo.event.topic.publish("XHRComplete", updatedIDs);
	dojo.debug("XHRComplete topic published");
	/* End add by rpack */
}

//
// Safely call responseComplete on the passed object, with the given response elements.
//
tacos._notifyListenerOnResponseComplete = function(updateObject, xmlResponseElements) {
    if (updateObject && typeof updateObject.responseComplete != "undefined")
        updateObject.responseComplete(xmlResponseElements);	
}

//
// Called to process an individual ajax-response element
//
tacos.loadElement = function(responseElement, responseId, kwArgs)
{
    var contents;
    if (responseElement.childNodes && responseElement.childNodes.length > 0) {
        for (var i = 0; i < responseElement.childNodes.length; i++) {
            var node = responseElement.childNodes[i];
            if (node.nodeType != 1) continue;
			
            var nodeId = node.getAttribute("id");
            if (nodeId && nodeId == responseId) {
                contents = node;
                break;
            }
        }
    } else {
        contents = responseElement;
    }
    if (dojo.byId(responseId)) {
        var localElement = dojo.byId(responseId);
		
        dojo.debug("responseId: " + responseId);
        localElement.innerHTML = tacos.getContentAsString(contents);
		
        //Process effects parameters
        if (kwArgs["effects"]) {
            tacos.processEffects(responseId, kwArgs["effects"]);
        }
		
        if (kwArgs["popup"]) {
            kwArgs["popup"].content = localElement.innerHTML;
            dojo.debug("popup content: " + kwArgs["popup"].content);
            tacos.processPopup(responseId, kwArgs["popup"]);
        }

        //Call optional updateObject
        if (kwArgs["updateObject"] && responseId != "scriptblock"
                && typeof kwArgs["updateObject"].ajaxUpdate != "undefined")
            kwArgs["updateObject"].ajaxUpdate(responseElement, localElement, responseId);
    } else {
    	dojo.debug("ERROR: tacos.loadElement() Unable to find element with id: " + responseId + " for ajax update.");
    }
}

//
//List all the effects that tacos supported.
//
tacos.supportedEffects = {
    highlight   : "dojo.lfx.html.highlight(effectElement, effectArguments).play()",
    fadeshow    :  "dojo.lfx.html.fadeShow(effectElement, effectArguments).play()",
    fadehide    :  "dojo.lfx.html.fadeHide(effectElement, effectArguments).play()",
    fade        :  "alert('fade effect removed in dojo 0.3.1... Use fadein or fadeout')",
    	//"dojo.fx.html.fade(effectElement, effectArguments)",// removed in dojo 0.3.1
    fadein      :  "dojo.lfx.html.fadeIn(effectElement, effectArguments).play()",
    fadeout     :  "dojo.lfx.html.fadeOut(effectElement, effectArguments).play()",
    wipein      :  "dojo.lfx.html.wipeIn(effectElement, effectArguments).play()",
    wipeout     :  "dojo.lfx.html.wipeOut(effectElement, effectArguments).play()",
    explode    	:  "dojo.lfx.html.explode(effectArguments).play()",
    implode  	:  "dojo.lfx.html.implode(effectArguments).play()",
    slideto  	:  "dojo.lfx.html.slideTo(effectElement, effectArguments).play()",
    slideby  	:  "dojo.lfx.html.slideBy(effectElement, effectArguments).play()",
	slide  		:  "alert('slide effect removed in dojo 0.3.1... Use slideto or slideby')"
		//"dojo.fx.html.slide(effectElement, effectArguments)"// removed in dojo 0.3.1            
};

//
// Called to process supported effects
//
tacos.processEffects = function(responseId, effectArgs)
{
    var elmid = "dojo.byId(" + dojo.lang.reprString(responseId) + ")";
    for (effectName in tacos.supportedEffects) {
        if (!effectArgs[effectName]) {
            continue;
        }
        var executed = tacos.supportedEffects[effectName];
        if (effectArgs[effectName][responseId]) {
            executed = executed.replace("effectArguments", effectArgs[effectName][responseId]);
            executed = executed.replace("effectElement", elmid);
            dojo.debug("processEffects(" + responseId + ") effect is:" + executed);
            eval(executed);
        } else if (effectArgs[effectName]["any"]) {
            executed = executed.replace("effectArguments", effectArgs[effectName]["any"]);
            executed = executed.replace("effectElement", elmid);
            dojo.debug("processEffects(" + responseId + ") ANY effect is:" + executed);
            eval(executed);
        } else {
          dojo.debug("processEffects(" + responseId + ") can't find matching effect for response");
        }
    }
}

//
// Called to process multiple effects
//
tacos.processMultipleEffects = function(effectArgs, updComponents)
{
	// hold elements that already have an effect on them.
	var processed = {};
	for (effect in effectArgs)
	{		
		for (elmtId in effectArgs[effect])
		{
			if (processed[elmtId])
				continue;
			processed[elmtId] = true;
			// if we find the any keyword, apply the effect to all updComponents
			if (elmtId=="any")
			{				
				if (updComponents)
				{
					for (var i=0; i<updComponents.length; i++)
					{
						anyId = updComponents[i];
						if (processed[anyId])
							continue;
						processed[anyId] = true;
						
						var addLine = "var addEffect = {'"+effect+"':{'"+anyId+"':'"+effectArgs[effect][elmtId]+"'}}";
						eval(addLine);
						tacos.processEffects(anyId, addEffect);
					}
				}
				continue;
			}
			var currLine = "var oneEffect = {'"+effect+"':{'"+elmtId+"':'"+effectArgs[effect][elmtId]+"'}}";
			eval(currLine);
			tacos.processEffects(elmtId, oneEffect);
		}
	}
}

//
// Last method called when response is completely processed
//
tacos.responseComplete = function(xmlResponseElements)
{
	tacos.requestsInFlight--;
    BoilerPlate.Cursor.resetCursor();
}

/* generates list of local client widgets */
tacos.getWidgetIds = function() {
	var widgets=dojo.widget.manager.getAllWidgets();
	var widgetIds = [];
	for (var i=0; i<widgets.length; i++){
		if (widgets[i].widgetId){
			widgetIds.push(widgets[i].wifgetId);
		}
	}
	return widgetIds.join(",");
}

//
// Core method called to initiate ajax request
//
tacos.defaultLinkAction = function(kwArgs)
{
    BoilerPlate.Cursor.setCursor("wait");
    if (kwArgs["targetLink"]) BoilerPlate.Cursor.setElementCursor(kwArgs["targetLink"], "wait");
    if (!kwArgs["content"]) kwArgs["content"] = {};
    kwArgs["content"]["dojoRequest"] = "true";
    kwArgs["content"]["processScripts"] = kwArgs["processScripts"];
    kwArgs["content"]["uuid"] = new Date();
    kwArgs["content"]["widgetids"] = tacos.getWidgetIds();
    
    dojo.io.bind({
        url: kwArgs["url"],
        content: kwArgs["content"],
        load: function(type, data, evt)
        {
            if (djConfig["isDebug"]) {
                dojo.info("Response:" + evt.responseText);
            }
            if (tacos.loadDojoResponse(type, data, evt, kwArgs)) {
              if (kwArgs["processScripts"] && data) {
                  tacos.processScripts(tacos.getContentAsString(
                          data.getElementsByTagName("ajax-response")[0]),
                          true);
              }
            }
        },
        error: function(type, error)
        {
            dojo.debug("Received error response of:" + error);
            tacos.responseComplete();
            document.clear();
            document.writeln(error);
        },
        sync: kwArgs["useSync"],
        mimetype: "text/xml",
        encoding: "UTF-8"
    });
    tacos.requestsInFlight++;
    return false;
}

//
// Function for submitting a tapestry form
//
tacos.formSubmit = function(kwArgs)
{
    BoilerPlate.Cursor.setCursor('wait');

/** MZ 7-3-09 Forcing No multipart forms
 * 
 */
	kwArgs["multipart"]=false;

    if (!kwArgs["content"]) {
        kwArgs["content"] = { dojoRequest: "true",
            processScripts: kwArgs["processScripts"]};
    }    
	// also submit the clicked button
  	if (kwArgs["btnId"]) {
  		var btnId = kwArgs["btnId"];
  		var btnValue = kwArgs["btnValue"];
  		if (kwArgs["multipart"]) {
  			kwArgs["content"]["_tacos_fix_" + btnId] = btnValue;  			
  		} else {
  			kwArgs["content"][btnId] = btnValue;
  		}  		
  	}
	
  //Experimental
  kwArgs["content"]["widgetids"] = tacos.getWidgetIds();

  // get stuff from url and put it in content if its a multipart
  if (kwArgs["multipart"]) {
	  var paramMap = tacos.parseQuery(kwArgs["url"]);
	  kwArgs["content"]["service"] = paramMap["service"];
	  
	  if (paramMap["updateid"]) {
	  	kwArgs["content"]["updateid"] = tacos._buildValueForMultipart(paramMap["updateid"]);
	  }
  }

  	var bindArgs = {
		// MZ 7-4-09 added for Dojo 1.1
		handleAs: "xml",
        url: kwArgs["url"],
        content: kwArgs["content"],
//        formNode: document.getElementById(kwArgs["formId"]),
 		form: document.getElementById(kwArgs["formId"]),
//        load: function(type, data, evt)
        load: function(data, ioArgs)

        {
            if (djConfig["isDebug"]) {
                dojo.debug("\nFormResponse:" + tacos.getContentAsString(data)+"\n");                    
			}
			/** MZ 7-4-09 Must remove for Dojo 1.1
        	if (kwArgs["multipart"]) {
        		dojo.debug("Multipart data submit response received.");
			    var response = data.getElementsByTagName("ajax-response");
			    if (response != null && response.length < 1) {
			    	data = tacos._fixIframeDataForIE(data);
			    }        		
        	}
        	**/
//            if (tacos.loadDojoResponse(type, data, evt, kwArgs)) {
           if (tacos.loadDojoResponse("load", data, ioArgs, kwArgs)) {
              if (kwArgs["processScripts"] && data) {
                  tacos.processScripts(tacos.getContentAsString(
                          data.getElementsByTagName("ajax-response")[0]),
                          true);
              }              			
            }
        },
        error: function(type, error)
        {
            dojo.debug("Received error response of type "
                  + type + " with error " + error.message);
            tacos.responseComplete();
        },
		// MZ 7-4-09 added for Dojo 1.1
		handleAs: "xml",
        multipart: kwArgs["multipart"]
    };
  	if (kwArgs["backLink"]) {
  		dojo.undo.browser.setInitialState(
  		{
  			back:function() {
  				eval(kwArgs["backLink"]);
  			}
  		});
  		
  		bindArgs["backButton"]=(function() {
  			eval(kwArgs["backLink"]);
  		})
  	}
  	if (kwArgs["forwardLink"]) {
  		bindArgs["forwardButton"]=(function() {
  			eval(kwArgs["forwardLink"]);
  		})
  	}
  	
    //Actual IO call to submit the form
//    dojo.io.bind(bindArgs);
	dojoSSN.xhrPost(bindArgs);
    tacos.requestsInFlight++;
    return false;
}

//Regexp matcher for javascript blocks in html content
tacos.ScriptFragment = '(?:<script.*?>)((\n|.|\r)*?)(?:<\/script>)';

//
// Evals <Script> contents of a returned respnose.
//
// text - The text string to check for scripts
// async - Whether to process the scripts synchronously or
//       asynchronously (ie on seperate thread)
//
tacos.processScripts = function(text, async)
{
	//if still processing another script come back
	if (tacos.processInFlight) {
		dojo.debug("processInFlight is true, sleeping");
		setTimeout(function() {
			tacos.processScripts(text, async);
		}, 5);
		return;
	}
	
    var match = new RegExp(tacos.ScriptFragment, 'img');
    var response = text.replace(match, '');
    var scripts = text.match(match);
	
    if (scripts) {
        match = new RegExp(tacos.ScriptFragment, 'im');
        if (async) {
            setTimeout(function()
            {
            		tacos.processInFlight = true;
                for (var i = 0; i < scripts.length; i++) {
                    var scr = scripts[i].match(match)[1];
                    try {
                        dojo.debug("evaluating script:" + scr);
                        eval(scr);
                    } catch (e) {
                        dojo.debug(e + " with script:" + scr);
                    }
                }
                tacos.processInFlight = false;
            }, 60);
        } else {
        		tacos.processInFlight = true;
            for (var i = 0; i < scripts.length; i++) {
                try {
                    var scr = scripts[i].match(match)[1];
                    dojo.debug("sync script eval of:" + scr);
                    eval(scr);
                } catch (e) {
                    dojo.debug("ERROR: processing script:" + e);
                }
            }
            tacos.processInFlight = false;
        }
    }
}

//
// Utility that returns nothing for <a href="javascript:tacos.noReturn();"></a> links.
//
tacos.noReturn = function()
{
}

//
// Loads a js package from the specified url
//
tacos.loadScriptFromUrl = function(url)
{
    //dojo.hostenv.loadUri(url);
    var scripts = window.document.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
        var src = scripts[i].src;
        if (src && src.length > 0 && src.indexOf(url)>=0 ) {
            return;
        }
    }
	
    var e = document.createElement("script");
    e.src = url;
    e.type = "text/javascript";
    document.getElementsByTagName("head")[0].appendChild(e);
}

//
// Utility that manages the creation of dojo
// FisheyeList widgets.
// ajax - Boolean, if true then content is coming from
//       an ajax response
// fishIds - Array of unique widget ids of each fisheye that needs building
// fishProps - Structure of properties to be used to build each
//            FisheyeList, the property set for a specific fisheye
//           is stored under fishProps[fishId].
//
tacos.buildFisheye = function(ajax, fishIds, fishProps)
{
    
    if (ajax) {
	    for (var i = 0; i < fishIds.length; i++) {
	        var fishEye = dojo.widget.byId(fishIds[i]);
	        //if ajax request we have to build it manually
	        if (ajax) {
	            dojo.debug("Creating fisheye with fishId:" + fishIds[i]);
	            djConfig.searchIds.push(fishIds[i]);
	            /* var fnode = dojo.byId(fishIds[i]);
	            dojo.debug("Fisheye dom node for " + fishIds[i] + " exists?:" + (fnode != null));
	            if (!fnode) {
	                dojo.debug("ERROR: Cant find old fisheye");
	                continue;
	            }
				
	            fishEye = dojo.widget.createWidget("FisheyeList",
	                    fishProps[fishIds[i]], fnode);
	            if (!fishEye) {
	                dojo.debug("ERROR: Unable to create FisheyeList with id:" + fishIds[i]);
	                return;
	            }
	            
	            document.body.appendChild(fishEye.domNode);
	            */
	        }     
	   }
	   
	   dojo.widget.widgetIds = [];
	   dojo.hostenv.makeWidgets();
	   dojo.hostenv.searchIds = [];
   } 
   for (var i = 0; i < fishIds.length; i++) {
   var fishEye = dojo.widget.byId(fishIds[i]);
   if (!fishEye) {
   	fishEye = dojo.widget.createWidget(fishIds[i]);
   	if (!fishEye) {
   		dojo.debug("ERROR: Unable to find fisheye with id:" + fishIds[i]);
   		continue;
   	}
   }
        //Fix element ids
        for (var e = 0; e < fishEye.children.length; e++) {
            var item = fishEye.children[e];
            if (item && item.domNode) {
                item.domNode.setAttribute("id", item.widgetId);
            } else {
              dojo.debug("item domNodeid: " + dojo.html.getAttribute(item.domNode, "id"));
                dojo.debug("Fisheye element doesn't have srcDiv or id attribute");
            }
        }
    }
}

//
// Attempts to build a dojo Dialog widget on the fly
//
tacos.buildDialog = function(ajax, elementId, hidden)
{
	dojo.require("dojo.widget.Manager");
	if (ajax) {
	    var cdialog = dojo.widget.byId(elementId);
		var node = dojo.byId(elementId);
		
		//if already exists
		if (cdialog) {
			cdialog.domNode.innerHTML = node.innerHTML;
		  	if (hidden)
		  		cdialog.hide();
		  	else
		  		cdialog.show();
		  		
		  	//dojo.dom.removeNode(node);
		  	return;
		}
		
		if (!node) {
		    dojo.debug("ERROR: Cant find dialog node with id:" + elementId);
		    return;
		}
		
		node.style.display = "none";
		cdialog = dojo.widget.createWidget("Dialog",
		          {id:elementId, widgetId:elementId}, node);
		dojo.widget.manager.widgetIds.push(elementId);
		if (!cdialog) {
		    dojo.debug("ERROR: Unable to create Dialog with id:" + elementId);
		    return;
		}
		
		if (!hidden)
			cdialog.show();
  	} else {
    		var cdialog = dojo.widget.byId(elementId);
      	if (cdialog) {
          dojo.widget.manager.widgetIds.push(elementId);
          
          if(!hidden)
          	cdialog.show();
      	} else {
      		//need to build it
      		var node = dojo.byId(elementId);
      		node.style.display = "none";
			cdialog = dojo.widget.createWidget("Dialog",
		          {id:elementId, widgetId:elementId}, node);
			dojo.widget.manager.widgetIds.push(elementId);
			if (!hidden)
				cdialog.show();
      	}
  	}
}

tacos.processPopup = function(responseId, popupArgs){
	
//    if(!popupArgs.contentNodeId){
//        popupArgs.contentNodeId = responseId;
//    }
    if(popupArgs.contentNodeId !=responseId){
        return;
    }
    tacos.showPopupPane(popupArgs);
}

//PeriodicalInvoker object.
tacos.PeriodicalInvoker = function(intervalMilliseconds, method, args) {
    this.intervalMilliseconds = intervalMilliseconds;
    this.method = method;
    this.args = args;
}

dojo.lang.extend(tacos.PeriodicalInvoker, {
    intervalMilliseconds: 1000,
    method: null,
    args: null,

    start: function(){
        dojo.require("dojo.animation.*");
        dojo.require("dojo.html");
        dojo.require("dojo.event.*");
        var line = new dojo.math.curves.Line([1],[1]);
        var delegate = new dojo.animation.Animation(line, this.intervalMilliseconds, 0, -1, this.intervalMilliseconds);
        dojo.event.connect(delegate, "onEnd", this, this._invoke);
        delegate.play(true);
    },

    _invoke: function(e){
    	
    	if(!this.args){
    		this.args = [];	
    	}
        this.method.apply(this, this.args);
    }
})

//
//Periodical invoke tacos.defaultLinkAction . 
//
tacos.createFormSubmitPeriodicalInvoker = function(intervalMilliseconds, functionName){
	var myFormSubmitEvent;
	if (document.createEvent){
		myFormSubmitEvent = document.createEvent("HTMLEvents");
		myFormSubmitEvent.initEvent("submit", true, true);
	}else{
		myFormSubmitEvent = document.createEventObject();
	}

	new tacos.PeriodicalInvoker(intervalMilliseconds, functionName, [myFormSubmitEvent]).start();
}

//
// handle the exception during any ajax request.
//
// Builds a floating exception window on error response, if
// the node with id tacosConfig.defaultExceptionConsoleId already exists, it's content
// will be targeted with the exception, otherwise a new node
// will be appended to the body.
//
// If a new node is created it will have a class attribute of
// "exception".
//
// htmlContent - String parsed html content response, will be
//				set on html node as innertHTMl
//
tacos.handleException = function(responseElement)
{
    if (!tacosConfig.popupWhenException) {
        dojo.debug("just replace defaultExceptionConsoleId's content with exception page!");
        var exceptionNode = dojo.byId(tacosConfig.defaultExceptionConsoleId);
        if(!exceptionNode){
            exceptionNode = document.createElement("div");
            exceptionNode.setAttribute("id",tacosConfig.defaultExceptionConsoleId);
            document.body.appendChild(exceptionNode);
        }
        exceptionNode.innerHTML = tacos.getContentAsString(responseElement);

    } else {

        dojo.debug("exception pane will be shown.");
        var fpArgs = {
            title:"Server Exception",
            widgetId:"exception",
            constrainToContainer:"1",
            toggle:'fade',
            resizable:true,
			displayCloseAction: true,
			displayMinimizeAction: true,
			displayMaximizeAction: true,
            persistenceWidgetPosition: true,
            //class:'exception',
            contentNodeId: tacosConfig.defaultExceptionConsoleId,
            content: tacos.getContentAsString(responseElement)
        }
        tacos.showPopupPane(fpArgs);
    }
}

//
// Show an Popup pane.
//
tacos.showPopupPane = function(floatingPaneArgs, isTaskBar)
{
    dojo.require("dojo.widget.FloatingPane");
    dojo.require("dojo.widget.ResizeHandle");
    dojo.require("dojo.widget.LayoutContainer");
    dojo.require("dojo.dom");
    
    if(!floatingPaneArgs["widgetId"] || (floatingPaneArgs["contentNodeId"] ==floatingPaneArgs["widgetId"])){
        floatingPaneArgs["widgetId"] = floatingPaneArgs["contentNodeId"] + "WidgetId";
        dojo.debug("widgetId isn't provided or is the same with contentNodeId!, using '"+floatingPaneArgs["widgetId"] + "' as widgetId");
    }

    if (floatingPaneArgs.isTaskBar)
        isTaskBar = true;
    if (isTaskBar)
        dojo.require("dojo.widget.TaskBar");
	
    var fpwidget = dojo.widget.getWidgetById(floatingPaneArgs["widgetId"]);
    var contentNode = dojo.byId(floatingPaneArgs["contentNodeId"]);

    if (!fpwidget) {
        dojo.debug("building a new floating pane!");
        var floatingPaneNode = tacos.createFloatingPaneNodeIfNotExists(floatingPaneArgs);
        
        if (!contentNode) {
            dojo.debug("creating content node");
            contentNode = document.createElement("div");
            contentNode.setAttribute("id", floatingPaneArgs["contentNodeId"]);
			
            var contentClass = "tacosFloatingPaneContent";
            if(floatingPaneArgs["contentNodeClass"]){
                 contentClass = floatingPaneArgs["contentNodeClass"];
            }
            dojo.html.addClass(contentNode, contentClass);
        }else{
            dojo.dom.removeNode(contentNode);
        }
		
        floatingPaneNode.appendChild(contentNode);
        if (isTaskBar)
            fpwidget = dojo.widget.createWidget("TaskBar", floatingPaneArgs, floatingPaneNode);
        else
            fpwidget = dojo.widget.createWidget("FloatingPane", floatingPaneArgs, floatingPaneNode);
        fpwidget.widgetId = floatingPaneArgs["widgetId"];
		
		//make sure widget id is being managed
		dojo.widget.widgetIds[fpwidget.widgetId] = fpwidget;
		
        if(floatingPaneArgs["persistenceWidgetPosition"]){
            tacos.initializeFloatingPane(floatingPaneArgs["widgetId"]);
        }
    }
	
    if(floatingPaneArgs["content"]){
        contentNode.innerHTML = floatingPaneArgs["content"];
        dojo.debug("content replaced!");
    }
    fpwidget.show();
}

//
//creating a FloatingPane if not exists.
//
tacos.createFloatingPaneNodeIfNotExists = function(floatingPaneArgs)
{	
    var floatingPaneNode = dojo.byId(floatingPaneArgs["widgetId"]);
    if (!floatingPaneNode) {
        floatingPaneNode = document.createElement("div");
        floatingPaneNode.setAttribute("id", floatingPaneArgs["widgetId"]);
    }
	
    if (floatingPaneArgs["class"]) {
        dojo.html.setClass(floatingPaneNode, floatingPaneArgs["class"]);
    }else{
        var styleText = "width: 640px; height: 480px; left: 100px; top: 100px";
        if(floatingPaneArgs["style"]){
            styleText = floatingPaneArgs["style"];
        }
        floatingPaneNode.style.cssText = styleText;
    }	
    
    document.body.appendChild(floatingPaneNode);	
    
    return floatingPaneNode;
}

//
// initialize the given floating pane.
//
tacos.initializeFloatingPane = function(floatingPaneId)
{
    var fpWidget = dojo.widget.byId(floatingPaneId);
    if (!fpWidget) {
        dojo.debug("NO Floating pane widget found with id:" + floatingPaneId);
        return;
    }		
	
    try {
	    var fp_state = tacos.readPaneState(floatingPaneId);
		var fp_left = fp_state.l;
		var fp_top = fp_state.t;
		var fp_width = fp_state.w;
		var fp_height = fp_state.h;    	
        dojo.debug("loading positions x,y,w,h:" + fp_left + "," 
       			  + fp_top + "," + fp_width + "," + fp_height);
        fpWidget.domNode.style.top = "40px";
        if (fp_left && fp_top)
        {
            fpWidget.domNode.style.left = fp_left;
            fpWidget.domNode.style.top = fp_top;
        }
        if (fp_width && fp_height)
        {
            //fpWidget.resizeTo(fp_width, fp_height);
            fpWidget.domNode.style.width = fp_width;
            fpWidget.domNode.style.height = fp_height;
        }
        
        var storePositionFunc = function(evt) {
		    var fpStyle = fpWidget.domNode.style;
			var obj = { l:fpStyle.left, t:fpStyle.top,
		        		w:fpStyle.width, h:fpStyle.height };        	        	
        	tacos.writePaneState(floatingPaneId, obj);        	
        };
		        
        //dojo.event.connect(fpWidget, "ondragend", storePositionFunc);
        if (fpWidget.domNode)		
        	dojo.event.connect(fpWidget.domNode, "onclick", storePositionFunc);		
        //dojo.event.connect(fpWidget, "onResized", storePositionFunc);
		
		fpWidget.resizeSoon();
		dojo.event.connect(fpWidget, "minimizeWindow", function(evt) {
			fpWidget.hide();
		});
    } catch (e) {
        dojo.debug("ERROR initializing floating pane with id:"
                + floatingPaneId + " " + e);
    }
}

//
// reads a pane's state from cookies
//
tacos.readPaneState = function(floatingPaneId) {
    var fp_coords_all_key = "fp_" + floatingPaneId + "_state";
    var state = dojo.io.cookie.getObjectCookie(fp_coords_all_key);    
    if (!state) 
    	state = {};
    if (state.t && parseInt(state.t)<5)
    	state.t = '5px';
    return state;
}

//
// writes a pane's state to cookies
//
tacos.writePaneState = function(floatingPaneId, obj, clearCurrent) {
    var fp_coords_all_key = "fp_" + floatingPaneId + "_state";
    // dojo.io.cookie.setObjectCookie(fp_coords_all_key, obj);
    var pairs = [], cookie, value = "";
    if(!clearCurrent) { cookie = tacos.readPaneState(floatingPaneId) }
    if(!cookie) { cookie = {}; }
	for(var prop in obj) {
		if(prop == null) {
			delete cookie[prop];
		} else if(typeof obj[prop] == "string" || typeof obj[prop] == "number") {
			cookie[prop] = obj[prop];
		}
	}
	prop = null;
	for(var prop in cookie) {
		pairs.push(escape(prop) + "=" + escape(cookie[prop]));
	}
	value = pairs.join("&");
	dojo.io.cookie.setCookie(fp_coords_all_key, value);
}

//
// Creates the debug console
//
tacos.createDebugConsole = function() {
	tacos.showPopupPane({	            
	            title:"<span>Debug Console - [ <a>Clear</a> ]</span>",
	            widgetId:"debugContainer",
	            constrainToContainer:true,
	            toggle:'fade',
	            displayMaximizeAction: true,
	            displayMinimizeAction: true,
	            hasShadow:!dojo.render.html.ie,
	            resizable:true,
	            contentNodeId:'ognlDebug',
	            persistenceWidgetPosition: true,            
	            style:'z-index:2000;width: 360px; height: 280px; left: 300px; top: 100px'
	            }); 
   
   dojo.html.addClass(dojo.widget.byId("debugContainer").titleBarText, "debugTitle");           
      
   var titleLinks = dojo.widget.byId("debugContainer").titleBarText.getElementsByTagName("a");
   
   dojo.event.connect(titleLinks[0], "onclick", function(evt)
   {
       dojo.dom.removeChildren(dojo.byId("dojoDebug"));
   });
   
   dojo.widget.byId("debugContainer").minimizeWindow = function()
   {
	   var dwbDc = dojo.widget.byId("debugContainer");
	   if (dwbDc.windowState!="minimized"){
	   dwbDc.windowState="minimized";
	   // store current height
	   dwbDc._tacosOldHeight = dwbDc.domNode.style.height;
	   dwbDc.containerNode.style.display = "none";
       dwbDc.resizeBar.style.display = "none";
	   dwbDc.resizeTo(2+parseInt(dwbDc.domNode.style.width), 28);       
       dwbDc.onResized();           		      
  	   tacos.writePaneState("debugContainer", {hide:"none"}, false);       	   
	   } else {
       dwbDc.windowState="normal";
	   dwbDc.containerNode.style.display = "";
       dwbDc.resizeBar.style.display = "";
	   dwbDc.resizeTo(2+parseInt(dwbDc.domNode.style.width), parseInt(dwbDc._tacosOldHeight));       		   
       dwbDc.onResized();        
   	   tacos.writePaneState("debugContainer", {hide:""}, false);
	  }
   };

	dojo.widget.byId("debugContainer")._maximizeWindow = dojo.widget.byId("debugContainer").maximizeWindow;
	dojo.widget.byId("debugContainer").maximizeWindow = function()
	{
		var dwbDc = dojo.widget.byId("debugContainer");
		if (dwbDc.windowState=="minimized")
			dwbDc.minimizeWindow();
		dwbDc._maximizeWindow();
	};
	
	dojo.widget.byId("debugContainer")._restoreWindow = dojo.widget.byId("debugContainer").restoreWindow;
	dojo.widget.byId("debugContainer").restoreWindow = function()
	{
		var dwbDc = dojo.widget.byId("debugContainer");
		if (dwbDc.windowState=="minimized")
			dwbDc.minimizeWindow();
		dwbDc._restoreWindow();
	};	
   
   dojo.event.connect(dojo.byId('tacosdc_js'), "onclick", function(evt)
   {	
	    try {
	   		dojo.info( "" + eval( dojo.byId('tacosdc_command').value ) );
		} catch (exc) {
			dojo.info("ERROR " + exc);
	   		}
       });     
   
   dojo.event.connect(dojo.byId('tacosdc_ognl'), "onclick", function(evt)
   {
		var ognl = dojo.byId('tacosdc_ognl');
		var realOgnl = dojo.byId('tacosdc_realognl');   
		if (!ognl.realUrl) {
			ognl.realUrl = realOgnl.href;
		}
		realOgnl.href = ognl.realUrl.replace("T_REPLACE", escape(dojo.byId('tacosdc_command').value));
		realOgnl.onclick();    			
   });         		

   // hide the panel initially?
   var currState = tacos.readPaneState("debugContainer").hide;
   if (currState && currState=="none" && !dojo.render.html.ie) {       			
   		dojo.widget.byId("debugContainer").minimizeWindow();
		dojo.widget.byId("debugContainer")._tacosOldHeight = "300px";
   }   	
}

tacos._ensureElementExists = function(id, className) {
    if (!document.getElementById(id)) {
        var block = document.createElement("div");
        block.setAttribute("id", id);
        if (className)
            Element.addClassName(block, className);
        document.body.appendChild(block);
    }
}

//
// Create ajax autocompleter
//
tacos.createAjaxAutocompleter = function(updId, inpId, updUrl, elmntClass, freq, options, afterUpdate) {
    if (typeof Ajax.Autocompleter == "undefined") {
        dojo.debug("Ajax.Autocompleter could not be resolved, script.aculo.us library required!");
        return;
    }

    tacos._ensureElementExists(updId, elmntClass);
    var updParams = { method: "get", frequency : freq, paramName: inpId };
    Object.extend(updParams, afterUpdate);
    Object.extend(updParams, options);

    new Ajax.Autocompleter(inpId, updId, updUrl, updParams);
}

//
// Create local autocompleter
//
tacos.createLocalAutocompleter = function(updId, inpId, values, elmntClass, freq, options, afterUpdate) {
    if (typeof Autocompleter.Local == "undefined") {
        dojo.debug("Autocompleter.Local could not be resolved, script.aculo.us library required!");
    }

    tacos._ensureElementExists(updId, elmntClass);
    var updParams = { method: "get", frequency : freq, paramName: inpId };
    Object.extend(updParams, afterUpdate);
    Object.extend(updParams, options);

    new Autocompleter.Local(inpId, updId, values, updParams);
}

tacos.default_invalid_field_handler = function(event, field, message) {
    if (!event.abort && !field.disabled)
    {
        Tapestry.set_focus(field);
          if ($(field.id + '-error'))
              Element.remove(field.id + '-error');

          new Insertion.Before(field.id,
          '<span id="' + field.id + '-error" style="font-style:italic;color:red;">' + message + '</span>');
          new Effect.Highlight(field.id + '-error', {endcolor: "#eeeee0"} );
          new Form.Element.Observer(field.id, 2,(function() {
               if ($(field.id + '-error')) {
                    Effect.Fade(field.id + '-error');
                    clearInterval(this.intervalVar);
               }
            }).bind(this));
        event.abort = true;
        event.cancel_handlers = true;
    }
}

tacos.set_focus = function(field) {
    if(typeof field == "string") {
        field = dojo.byId(field);

        if(field) {
            if (!field.disabled && field.clientWidth > 0) {
                if (field.focus) {
                    field.focus();
                }

                if (field.isContentEditable || field.isContentEditable == null) {
                    if (field.select) {
                        field.select();
                    }
                }
            }
        }
    }
}

//
// Parses a query string and returns a key-value map. Each value is a string,
// unless a key appears more than once (in that case, it's an array of strings)
//
tacos.parseQuery = function(queryString) {
  var pos = queryString.indexOf("?");
  if (pos>=0)
      queryString = queryString.substring(pos);
  var pairs = queryString.match(/^\??(.*)$/)[1].split('&');
  return pairs.inject({}, function(params, pairString) {
    var pair = pairString.split('=');
    if (params[pair[0]]) {
        if (!params[pair[0]].push) {params[pair[0]] = new Array(params[pair[0]]);}
  		  params[pair[0]].push(pair[1]);
    }
    else {
        params[pair[0]] = pair[1];
    }
    return params;
  });
}

//
// If the arg is an array, concat all elements with newlines in between
// NOTE: dojo accepts arrays in content but only for BrowserIO transfer
tacos._buildValueForMultipart = function(updId) {
  	if (typeof updId != 'string') {
  		var updArr = updId;
  		updId = "";
  		for (var i=0; i<updArr.length; i++) {
  			updId += updArr[i] + "\n";
  		}
  		if (updId.length > 0) {
  			updId = updId.substring(0, updId.length - 1);
  		}
  	}
  	return updId;
}

//
// Used by Form.js to register forms a little differently
// than the tapestry default.
//
// formId - String unique id of form
//
tacos.registerForm = function(formId) {
  if (tacos.forms[formId]) delete tacos.forms[formId];
  tacos.forms[formId] = {};
  tacos.forms[formId]["form"] = dojo.byId(formId);
  tacos.forms[formId]["handlers"] = [];
}

//
// Called by Form.js on<event> methods to enable execution
// of validation/etc functions during a form post.
//
// formId - Unique form id
// handler - JS function to be called
//
tacos.addFormHandler = function(formId, handler) {
  if (!tacos.forms[formId]) return;
  tacos.forms[formId]["handlers"].push(handler);
}

//
// Executes the stored handlers for the specified form.
//
// formId - Unique form id
// event - Original javascript event that triggered the form
//		   submission.
//
tacos.applyFormHandlers = function(formId, event) {
  if (!tacos.forms[formId]) return;
  var frm = dojo.byId(formId);
  if (frm.submitmode && frm.submitmode.value!='') return;

  var handlers = tacos.forms[formId]["handlers"];
  for (var i=0; i < handlers.length; i++) {
    handlers[i].call(window, event);
  }
}

tacos._submitFormAs = function(frm, submitType) {
	frm = dojo.byId(frm);
		
	if (!frm) return;
	
	var event;
	if (document.createEvent)
		event = document.createEvent("MouseEvents");
	else {
		event = document.createEventObject();
		event = dojo.event.browser.fixEvent(event);
	}	
	
	if (frm.submitmode)
    	frm.submitmode.value = submitType; 
    	
	//frm['on' + submitType](event);// this breaks IE	
	if (submitType == 'cancel') frm.oncancel(event);
	if (submitType == 'refresh') frm.onrefresh(event);
	if (submitType == 'submit') frm.onsubmit(event);		
	
	if (frm.submitmode)
    	frm.submitmode.value = '';	
}

tacos.cancelForm = function(formId) {
	tacos._submitFormAs(formId, "cancel");
}

tacos.refreshForm = function(formId) {
	tacos._submitFormAs(formId, "refresh");
}

tacos.connectForm = function(formId, funcName) {
	dojo.event.connect(dojo.byId(formId), "onsubmit", document, funcName);
	dojo.event.connect(dojo.byId(formId), "oncancel", document, funcName);
	dojo.event.connect(dojo.byId(formId), "onrefresh", document, funcName);
}

tacos.disconnectForm = function(formId, funcName) {
	dojo.event.disconnect(dojo.byId(formId), "onsubmit", document, funcName);
	dojo.event.disconnect(dojo.byId(formId), "oncancel", document, funcName);
	dojo.event.disconnect(dojo.byId(formId), "onrefresh", document, funcName);
}

//
// Some dojo debug console logging ideas I'm playing with
//
dojo.infoDIV = document.createElement("span");
dojo.infoDIV.setAttribute("style", "font-weight:bold;color:#000000;");
dojo.infoDIV.appendChild(document.createTextNode("INFO:"));

dojo.info = function(info)
{
    try {
        var console = document.getElementById(djConfig.debugContainerId ?
                                              djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
        if (!console) {
            console = document.getElementsByTagName("body")[0] || document.body;
        }

        var div = document.createElement("div");
        div.setAttribute("style", "display:block; width:100%;"
                + "background:#BFE0F1;color:#000000;"
                + "border-top:1px solid #80C1E3;border-bottom:1px solid #80C1E3;");
        div.appendChild(dojo.infoDIV);
        div.appendChild(document.createTextNode(info));
        console.appendChild(div);
    } catch (e) {
        try {
            // safari needs the output wrapped in an element for some reason
            document.write("<div>INFO:" + info + "</div>");
        } catch(e2) {
            window.status = "INFO" + info;
        }
    }
    // scroll to bottom
    tacos._scrollDebugConsole();
    if (tacosConfig.outputResponseLength)
        dojo.debug("Bytes: " + info.length);
}

tacos._scrollDebugConsole = function() {
    var dcci = dojo.byId('debugconsoleContentId');
    if (dcci && dcci.scrollTop < dcci.scrollHeight) {
    	var newPos = dcci.scrollTop + 20;
    	if (newPos > dcci.scrollHeight) newPos = dcci.scrollHeight;
	    dcci.scrollTop = newPos;
	    if (dcci.scrollTop == newPos)
	    	setTimeout("tacos._scrollDebugConsole()", 30);
    }
}

function windowError(message, url, line)
{
    FVL_log('Error on line ' + line + ' of document ' + url + ': ' + message, FVL_FATAL);
    return true;
    //
}

// only override the window's error handler if we logging is turned on
if (djConfig["isDebug"]) {
    dojo.event.connect(window, "onerror", function(msg, url, line)
    {
        dojo.debug("ERROR: On line " + line + " of document " + url
                + ": " + msg);
    });
}