/**
 @fileoverview
 This JavaScript file describes actions for sending ajax requests using Taconite.
 */

function doAjaxAction(eventId, sourceElement, jsonObject) {
    
    var ajaxRequest = new AjaxRequest(document.URL);
    ajaxRequest.addFormElementsByFormEl(document.forms[0]);
    ajaxRequest.setQueryString(ajaxRequest.getQueryString() + "&ajax-request=ajax-action" + "&event-id=" + eventId + createSimpleQueryString(sourceElement) + createJSONQueryString(jsonObject));
    if(jsonObject.keyName == 'brands' && jsonObject.keyName == 'services'){
     alert(jsonObject.keyName);
    ajaxRequest.setUsePOST();
    }
    ajaxRequest.setUsePOST();
    ajaxRequest.sendRequest();
}

function doAjaxSubmit(eventId, sourceElement, jsonObject) {
    var ajaxRequest = new AjaxRequest(document.URL);
    ajaxRequest.addFormElementsByFormEl(document.forms[0]);
    ajaxRequest.setQueryString(ajaxRequest.getQueryString() + "&ajax-request=ajax-submit" + "&event-id=" + eventId + createSimpleQueryString(sourceElement) + createJSONQueryString(jsonObject));
    ajaxRequest.setUsePOST(); 
    ajaxRequest.sendRequest();
}

function createSimpleQueryString(sourceElement) {
    var qs = "";
    if (sourceElement != undefined && sourceElement != null) {
        if (sourceElement.name != null && sourceElement.name != "") {
            qs = qs + "&source-element=" + sourceElement.name;
        }
        if (sourceElement.id != null && sourceElement.id != "") {
            qs = qs + "&source-element-id=" + sourceElement.id;
        }
    }
    return qs;
}

function createJSONQueryString(jsonObject) {
    var qs = "";
    if (jsonObject != undefined && jsonObject != null) {
        qs = "&json-params=" + escape(JSON.stringify(jsonObject));
    }
    return qs;
}

var XT = {
    
    doAjaxAction : doAjaxAction,
    
    doAjaxSubmit : doAjaxSubmit
};
/**
 @fileoverview
 This JavaScript file represents the core browser-side functionality
 supplied by Taconite. In general, the tools in this file wrap an instance
 of XMLHttpRequest object and provide utility methods for gather data from
 form elements to be sent to the server as par of an Ajax request.
 */

/**
 Constructor for the AjaxRequest class. 
 
 <br><br>
 Example:
 
 <br><br>
 var ajaxRequest = new AjaxRequest("YOUR_URL");
 
 @class The AjaxRequest object wraps an instance of XMLHttpRequest and provides 
 facilities for setting functions that are called before a request is made
 and after a request returns. By default, AjaxRequest handles the server
 response by simply calling eval(), passing to it the responseText from 
 the XMLHttpRequestObject, of course assuming that the response was 
 generated by Taconite on the server side and that running eval() will 
 update the web page.<br><br>Example Usage:<br><br>var ajaxRequest = new AjaxRequest("YOUR_URL");
 <br>ajaxRequest.addFormElements("form_element_id_attribute_value");
 <br>ajaxRequest.sendRequest();
 
 @constructor
 @param {String} a String repesenting the URL to which the Ajax request
 will be sent.
 */
var taconite_client_version=1.6;
function AjaxRequest(url) {
    /** @private */
    var self = this;
    
    /** @private */
    var xmlHttp = createXMLHttpRequest();
    
    /** @private */
    var queryString = "";
    
    /** @private */
    var requestURL = url;
    
    /** @private */
    var method = "GET";
    
    /** @private */
    var preRequest = null;
    
    /** @private */
    var postRequest = null;
    
    /** @private */
    var debugResponse = false;
    
    /** @private */
    var async = true;
    
    /** @private errorHandler*/ 
    var errorHandler = null;
    
    
    /**
     Return the instance of the XMLHttpRequest object wrapped by this object.
     @return XMLHttpRequest
     */
    this.getXMLHttpRequestObject = function() {
        return xmlHttp;
    }
    
    /**
     Set the pre-request function. This function will be called prior to 
     sending the Ajax request. The pre-request function is passed a reference
     to this object.
     @param {Function} The function to be called prior to sending the Ajax
     request. The function is passed a refernce of this object.
     */
    this.setPreRequest = function(func) {
        preRequest = func;
    }
    
    /**
     Set the post-request function. This function will be called after the
     response has been received and after eval() has been called using the 
     XMLHttpRequest object's responseText. The post-request function is passed 
     a reference to this object.
     @param {Function} The function to be called after receiving the Ajax
     response. The function is passed a refernce of this object.
     */
    this.setPostRequest = function(func) {
        postRequest = func;
    }
    
    /**
     Return the post request function.
     */
    this.getPostRequest = function() {
        return postRequest;
    }
    
    /**
     Send the Ajax request using the POST method. Use with caution -- some
     browsers do not support the POST method with the XMLHttpRequest object.
     */
    this.setUsePOST = function() {
        method = "POST";
    }
    
    /**
     Send the Ajax request using the GET method, where parameters are sent
     as a query string appended to the URL. This is the default behavior.
     */
    this.setUseGET = function() {
        method = "GET";
    }
    
    /**
     Enable client-side debugging.  The server's response will be written
     to a text area appended to the bottom of the page.  If parsing is
     performed on the client side, then the results of the parsing operations
     are shown in their own text areas.
     */
    this.setEchoDebugInfo = function() {
        debugResponse = true;
    }
    
    /**
     Indicate if debugging is enabled.
     @return boolean
     */
    this.isEchoDebugInfo = function() {
        return debugResponse;
    }
    
    /**
     Set the query string that will be sent to the server. For GET
     requests, the query string is appended to the URL. For POST
     requests, the query string is sent in the request body. This 
     method is useful, for example, if you want to send an XML string
     or JSON string to the server.
     @param {String} qa, the new query string value.
     */
    this.setQueryString = function(qs) {
        queryString = qs;
    }
    
    /**
     Return the query string.
     @return The query string.
     */
    this.getQueryString = function() {
        return queryString;
    }
    
    /** 
     @param {Boolean} asyncBoolean, set to true if asynchronous request, false synchronous request. 
     */
    this.setAsync = function(asyncBoolean){
        async = asyncBoolean;
    }
    
    /** 
     @param {Function} Set the error handler function that is called if the 
     server's HTTP response code is something other than 200.
     */	
    this.setErrorHandler = function(func){
        errorHandler = func;
    }
    
    /**
     Add all of the form elements under the specified form to the query
     string to be sent to the server as part of the Ajax request. The values
     are automatically encoded.
     @param {String} formID, the value of the id attribute of the form from
     which you wish to accumulate the form values.
     */
    this.addFormElements = function(formID) {
        var formElements = document.getElementById(formID).elements;
        var values = toQueryString(formElements);
        accumulateQueryString(values);
    }
    
    /**
     Add all of the form elements under the specified form to the query
     string to be sent to the server as part of the Ajax request. The values
     are automatically encoded.
     @param {String} formEl, the form element from
     which you wish to accumulate the form values.
     */
    this.addFormElementsByFormEl = function(formEl) {
        var formElements = formEl.elements;
        var values = toQueryString(formElements);
        accumulateQueryString(values);
    }
    
    /** @private */
    function accumulateQueryString(newValues) {
        if(queryString == "") {
            queryString = newValues; 
        }
        else {
            queryString = queryString + "&" +  newValues;
        }
    }
    
    /**
     Add the name/value pair to the query string.
     @param {String} name
     @param {String} value
     */
    this.addNameValuePair = function(name, value) {
        var nameValuePair = name + "=" + encodeURIComponent(value);
        accumulateQueryString(nameValuePair);
    }
    
    /**
     Same as addNamedFormElements, except it will filter form elements by form's id.
     For example, these are all valid uses:<br>
     <br>ajaxRequest.addNamedFormElements("form-id""element-name-1");
     <br>ajaxRequest.addNamedFormElements("form-id","element-name-1",
     "element-name-2", "element-name-3");
     */
    this.addNamedFormElementsByFormID = function() {
        var elementName = "";
        var namedElements = null;
        
        for(var i = 1; i < arguments.length; i++) {
            elementName = arguments[i];
            namedElements = document.getElementsByName(elementName);
            var arNamedElements = new Array();
            for(j = 0; j < namedElements.length; j++) {
                if(namedElements[j].form  && namedElements[j].form.getAttribute("id") == arguments[0]){
                    arNamedElements.push(namedElements[j]);				
                }
            }
            if(arNamedElements.length > 0){
                elementValues = toQueryString(arNamedElements);
                accumulateQueryString(elementValues);
            }
        }
    }
    
    /**
     Add the values of the named form elements to the query string to be
     sent to the server as part of the Ajax request. This method takes any 
     number of Strings representing the form elements for wish you wish to 
     accumulate the values. The Strings must be the value of the element's 
     name attribute.<br><br>For example, these are all valid uses:<br>
     <br>ajaxRequest.addNamedFormElements("element-name-1");
     <br>ajaxRequest.addNamedFormElements("element-name-1", "element-name-2", "element-name-3");
     */
    this.addNamedFormElements = function() {
        var elementName = "";
        var namedElements = null;
        
        for(var i = 0; i < arguments.length; i++) {
            elementName = arguments[i];
            namedElements = document.getElementsByName(elementName);
            
            elementValues = toQueryString(namedElements);
            
            accumulateQueryString(elementValues);
        }
        
    }
    
    /**
     Add the values of the id'd form elements to the query string to be
     sent to the server as part of the Ajax request. This method takes any 
     number of Strings representing the ids of the form elements for wish you wish to 
     accumulate the values. The Strings must be the value of the element's 
     name attribute.<br><br>For example, these are all valid uses:<br>
     <br>ajaxRequest.addFormElementsById("element-id-1");
     <br>ajaxRequest.addFormElementsById("element-id-1", "element-id-2", "element-id-3");
     */
    this.addFormElementsById = function() {
        var id = "";
        var element = null;
        var elements = new Array();
        
        for(var h = 0; h < arguments.length; h++) {
            element = document.getElementById(arguments[h]);
            if(element != null) {
                elements[h] = element;
            }
        }
        
        elementValues = toQueryString(elements);
        accumulateQueryString(elementValues);
    }
    
    /**
     Send the Ajax request.
     */
    this.sendRequest = function() {
        if(preRequest) {
            preRequest(self);
        }
        
        var obj = this;
        if(async)
            xmlHttp.onreadystatechange = function () { handleStateChange(self) };
            
            if(requestURL.indexOf("?") > 0) {
                requestURL = requestURL + "&ts=" + new Date().getTime();
            }
            else {
                requestURL = requestURL + "?ts=" + new Date().getTime();
            }
            
            try {
                if(method == "GET") {
                    if(queryString.length > 0) {
                        requestURL = requestURL + "&" + queryString;
                    }
                    xmlHttp.open(method, requestURL, async);
                    xmlHttp.send(null);
                }
                else {
                    xmlHttp.open(method, requestURL, async);
                    //Fix a bug in Firefox when posting
                    try {
                        if (xmlHttp.overrideMimeType) {
                            xmlHttp.setRequestHeader("Connection", "close");//set header after open
                        }			
                    }
                    catch(e) {
                        // Do nothing
                    }
                    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
                    xmlHttp.send(queryString);
                }
            }
            catch(exception) {
                if(errorHandler) {
                    errorHandler(self, exception);
                }
                else {
                    throw exception;
                }
            }
            
            if(!async) {  //synchronous request, handle the state change
                handleStateChange(self);
            }
            
            if(self.isEchoDebugInfo()) {
                echoRequestParams();
            }
    }
    
    handleStateChange = function(ajaxRequest) {
        if(ajaxRequest.getXMLHttpRequestObject().readyState != 4) {
            return;
        }
        try {
            var debug = ajaxRequest.isEchoDebugInfo();
            if(debug) {
                echoResponse(ajaxRequest);
            }
            
            //handle null responseXML
            var nodes = null;
            if (ajaxRequest.getXMLHttpRequestObject().responseXML != null) {
                nodes = ajaxRequest.getXMLHttpRequestObject().responseXML.documentElement.childNodes;
            }
            else {
                nodes = new Array();
            }
            
            var parser = new XhtmlToDOMParser();
            var parseInBrowser = "";
            for(var i = 0; i < nodes.length; i++) {
                if(nodes[i].nodeType != 1 || !isTaconiteTag(nodes[i])) {
                    continue;
                }
                
                parseInBrowser = nodes[i].getAttribute("parseInBrowser");
                if(parseInBrowser == "true") {
                    parser.parseXhtml(nodes[i]);
                    var js = parser.getJavaScript();
                    if(debug) {
                        echoParsedJavaScript(js);
                    }
                }
                else {
                    eval(nodes[i].firstChild.nodeValue);
                }
            }
            
            if(ajaxRequest.getPostRequest()) {
                var f = ajaxRequest.getPostRequest();
                f(ajaxRequest);
            }
        }
        catch(exception) {
            if(errorHandler) {
                errorHandler(self, exception);
            }
            else {
                throw exception;
            }
        }
    }
    
    /** @private */
    function isTaconiteTag(node) {
        return node.tagName.substring(0, 9) == "taconite-";
    }
    
    /** @private */
    function toQueryString(elements) {
        var node = null;
        var qs = "";
        var name = "";
        
        var tempString = "";
        for(var i = 0; i < elements.length; i++) {
            tempString = "";
            node = elements[i];
            name = node.getAttribute("name");
            
            //use id if name is null
            if (!name) {
                name = node.getAttribute("id");
            }
            
            if(node.tagName.toLowerCase() == "input") {
                if(node.type.toLowerCase() == "radio" || node.type.toLowerCase() == "checkbox") {
                    if(node.checked) {
                        tempString = name + "=" + node.value;
                    }
                }
                
                if(node.type.toLowerCase() == "text" || node.type.toLowerCase() == "hidden" || node.type.toLowerCase() == "password") {
                    tempString = name + "=" + encodeURIComponent(node.value);
                }
            }
            else if(node.tagName.toLowerCase() == "select") {
                tempString = getSelectedOptions(node);
            }
            
            else if(node.tagName.toLowerCase() == "textarea") {
                tempString = name + "=" + encodeURIComponent(node.value);
            }
            
            if(tempString != "") {
                if(qs == "") {
                    qs = tempString;
                }
                else {
                    qs = qs + "&" + tempString;
                }
            }
            
        }
        
        return qs;
        
    }
    
    /** @private */
    function getSelectedOptions(select) {
        var options = select.options;
        var option = null;
        var qs = "";
        var tempString = "";
        
        for(var x = 0; x < options.length; x++) {
            tempString = "";
            option = options[x];
            
            if(option.selected) {
                tempString = select.name + "=" + option.value;
            }
            
            if(tempString != "") {
                if(qs == "") {
                    qs = tempString;
                }
                else {
                    qs = qs + "&" + tempString;
                }
            }
        }
        
        return qs;
    }
    
    /** @private */
    function echoResponse(ajaxRequest) {
        var echoTextArea = document.getElementById("debugResponse");
        if(echoTextArea == null) {
            echoTextArea = createDebugTextArea("Server Response:", "debugResponse");
        }
        var debugText = ajaxRequest.getXMLHttpRequestObject().status 
        + " " + ajaxRequest.getXMLHttpRequestObject().statusText + "\n\n\n";
        echoTextArea.value = debugText + ajaxRequest.getXMLHttpRequestObject().responseText;
    }
    
    /** @private */
    function echoParsedJavaScript(js) {
        var echoTextArea = document.getElementById("debugParsedJavaScript");
        if(echoTextArea == null) {
            var echoTextArea = createDebugTextArea("Parsed JavaScript (by JavaScript Parser):", "debugParsedJavaScript");
        }
        echoTextArea.value = js;
    }
    
    /** @private */
    function createDebugTextArea(label, id) {
        echoTextArea = document.createElement("textarea");
        echoTextArea.setAttribute("id", id);
        echoTextArea.setAttribute("rows", "15");
        echoTextArea.setAttribute("style", "width:100%");
        echoTextArea.style.cssText = "width:100%";
        
        document.getElementsByTagName("body")[0].appendChild(document.createTextNode(label));
        document.getElementsByTagName("body")[0].appendChild(echoTextArea);
        return echoTextArea;
    }
    
    
    /** @private */
    function echoRequestParams() {
        var qsTextBox = document.getElementById("qsTextBox");
        if(qsTextBox == null) {
            qsTextBox = createDebugTextBox("Query String:", "qsTextBox");
        }
        qsTextBox.value = queryString;
        
        var urlTextBox = document.getElementById("urlTextBox");
        if(urlTextBox == null) {
            urlTextBox = createDebugTextBox("URL (Includes query string if GET request):", "urlTextBox");
        }
        urlTextBox.value = requestURL;
    }
    
    /** @private */
    function createDebugTextBox(label, id) {
        textBox = document.createElement("input");
        textBox.setAttribute("type", "text");
        textBox.setAttribute("id", id);
        textBox.setAttribute("style", "width:100%");
        textBox.style.cssText = "width:100%";
        
        document.getElementsByTagName("body")[0].appendChild(document.createTextNode(label));
        document.getElementsByTagName("body")[0].appendChild(textBox);
        return textBox;
    }
    
    
}

/**
 Create an instance of the XMLHttpRequest object, using the appropriate
 method for the type of browser in which this script is running. For Internet
 Explorer, it's an ActiveX object, for all others it's a native JavaScript
 object.
 @return an instance of the XMLHttpRequest object.
 */
function createXMLHttpRequest() {
    var req = false;
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
        try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch(e) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(e) {
                req = false;
            }
        }
    }
    return req;
}
// JavaScript Document
var taconite_parser_version=1.502;
var isIE=document.uniqueID;
String.prototype.trim = function() {
    //skip leading and trailing whitespace
    //and return everything in between
    var x=this;
    x=x.replace(/^\s*(.*)/, "$1");
    x=x.replace(/(.*?)\s*$/, "$1");
    return x;
};

function requiresContextNode(xmlTagName) {
    return !(xmlTagName == "taconite-execute-javascript" || xmlTagName == "taconite-redirect");
}

function XhtmlToDOMParser() {
    
    this.parseXhtml = function(xml){
        var xmlTagName=xml.tagName.toLowerCase();
        var contextNode=document.getElementById(xml.getAttribute("contextNodeID"));
        if(contextNode == null && requiresContextNode(xmlTagName)){
            return false;
        }
        switch (xmlTagName) {
            case "taconite-append-as-children":
                getReplaceChildren(contextNode,xml,false);
                break;
            case "taconite-delete":
                getDelete(contextNode,xml);
                break;
            case "taconite-append-as-first-child":
                getAppendAsFirstChild(contextNode,xml);
                break;                         
            case "taconite-insert-after":
                getInsertAfter(contextNode,xml);
                break;
            case "taconite-insert-before":
                getInsertBefore(contextNode,xml);
                break;                         
            case "taconite-replace-children":
                getReplaceChildren(contextNode,xml,true);
                break;
            case "taconite-replace":
                getReplace(contextNode,xml);
                break;                         
            case "taconite-set-attributes":
                xml.removeAttribute("contextNodeID");
                xml.removeAttribute("parseInBrowser");
                handleAttributes(contextNode,xml);
                break;
            case "taconite-redirect":
                handleRedirect(xml);
                break;
            case "taconite-execute-javascript":
                executeJavascript(xml);
                break;
        }  
        return true;
    };
    
    function isInlineMode(node) {
        var attrType;
        if(!node.tagName.toLowerCase() == "input") {
            return false;
        }
        attrType=node.getAttribute("type");
        
        if(attrType=="radio" || attrType=="checkbox") {
            return true;
        }
        return false;
    }  
    
    this.getJavaScript= function() {
        return "var dummy_taconite_variable=0";
    }; 
    
    function handleNode(xmlNode){
        var nodeType = xmlNode.nodeType;               
        switch(nodeType) {
            case 1:  //ELEMENT_NODE
                return handleElement(xmlNode);
            case 3:  //TEXT_NODE
            case 4:  //CDATA_SECTION_NODE
                var textNode = document.createTextNode(xmlNode.nodeValue);
                if(isIE) {
                    textNode.nodeValue = textNode.nodeValue.replace(/\n/g, '\r'); 
                }
                return textNode;
        }      
        return null;
    }
    
    function handleElement(xmlNode){
        var domElemNode=null;
        var xmlNodeTagName=xmlNode.tagName.toLowerCase();
        if(isIE){
            if(isInlineMode(xmlNode)) {
                return document.createElement("<INPUT " + handleAttributes(domElemNode,xmlNode,true) + ">");
            }
            if(xmlNodeTagName == "style"){
                //In internet explorer, we have to use styleSheets array.		
                var text,rulesArray,styleSheetPtr;
                var regExp = /\s+/g;
                text=xmlNode.text.replace(regExp, " ");
                rulesArray=text.split("}");
                
                domElemNode=document.createElement("style");
                styleSheetPtr=document.styleSheets[document.styleSheets.length-1];
                for(var i=0;i<rulesArray.length;i++){
                    rulesArray[i]=rulesArray[i].trim();
                    var rulePart=rulesArray[i].split("{");
                    if(rulePart.length==2) {//Add only if the rule is valid
                        styleSheetPtr.addRule(rulePart[0],rulePart[1],-1);//Append at the end of stylesheet.
                    }
                }							
                return domElemNode;			
            }
            
        }
        if(domElemNode == null){
            if(useIEFormElementCreationStrategy(xmlNodeTagName)) {
                domElemNode = createFormElementsForIEStrategy(xmlNode);
            }
            else {
                domElemNode = document.createElement(xmlNodeTagName);
            }
            
            handleAttributes(domElemNode,xmlNode);
            //Fix for IE Script tag: Unexpected call to method or property access error
            //IE don't allow script tag to have child
            if(isIE && !domElemNode.canHaveChildren){
                if(xmlNode.childNodes.length > 0){
                    domElemNode.text=xmlNode.text;
                }
                
            }                              
            else{
                for(var z = 0; z < xmlNode.childNodes.length; z++) {
                    var domChildNode=handleNode(xmlNode.childNodes[z]);
                    if(domChildNode!=null) {
                        domElemNode.appendChild(domChildNode);
                    }
                }
            }
        }      
        
        return domElemNode;
    }
    
    function useIEFormElementCreationStrategy(xmlNodeTagName) {
        var useIEStrategy = false;
        
        if (isIE && ( xmlNodeTagName.toLowerCase() == "form" ||
        xmlNodeTagName.toLowerCase() == "input" ||
        xmlNodeTagName.toLowerCase() == "textarea" ||
        xmlNodeTagName.toLowerCase() == "select" ||
        xmlNodeTagName.toLowerCase() == "a" ||
        xmlNodeTagName.toLowerCase() == "applet" ||
        xmlNodeTagName.toLowerCase() == "button" ||
        xmlNodeTagName.toLowerCase() == "img" ||
        xmlNodeTagName.toLowerCase() == "link" ||
        xmlNodeTagName.toLowerCase() == "map" ||
        xmlNodeTagName.toLowerCase() == "object")) {
            
            useIEStrategy = true;
        }
        
        return useIEStrategy;
    }
    
    function createFormElementsForIEStrategy(xmlNode) {
        var attr = null;
        var name = "";
        var value = "";
        for (var x = 0; x < xmlNode.attributes.length; x++) {
            attr = xmlNode.attributes[x];
            name = attr.name.trim();
            if (name == "name") {
                value = attr.value.trim();
            }
        }
        
        domElemNode = document.createElement("<" + xmlNode.tagName + " name='" + value + "' />"); // e.g. document.createElement("<input name='slot2'>");
        
        return domElemNode;
    }
    
    function handleAttributes(domNode, xmlNode) {
        var attr = null;
        var attrString = "";
        var name = "";
        var value = "";
        var returnAsText = false;
        if(arguments.length == 3) {
            returnAsText = true;
        }
        
        for(var x = 0; x < xmlNode.attributes.length; x++) {
            attr = xmlNode.attributes[x];
            name = cleanAttributeName(attr.name.trim());
            value = attr.value.trim();
            if(!returnAsText){
                if(name == "style") {
                    /* IE workaround */
                    domNode.style.cssText = value;
                    /* Standards compliant */
                    domNode.setAttribute(name, value);
                }
                else if(name.trim().toLowerCase().substring(0, 2) == "on") {
                    /* IE workaround for event handlers */
                    //domNode.setAttribute(name,value);
                    eval("domNode." + name.trim().toLowerCase() + "=function(){" + value + "}");
                }
                else if(name == "value") {
                    /* IE workaround for the value attribute -- makes form elements selectable/editable */
                    domNode.value = value;
                }
                else if(useIEFormElementCreationStrategy(xmlNode.tagName) && name == "name") {
                    //Do nothing, as the "name" attribute was handled in the createFormElementsForIEStrategy function
                    continue;
                }
                else {
                    /* Standards compliant */
                    domNode.setAttribute(name,value);
                }
                /* class attribute workaround for IE */
                if(name == "class") {
                    domNode.setAttribute("className",value);
                }
            }else{
                attrString = attrString + name + "=\"" + value + "\" " ;
            }
        }
        return attrString;
    }
    
    function getAppendAsFirstChild(domNode,xml){
        var firstNode=null;
        if(domNode.childNodes.length > 0) {
            firstNode=domNode.childNodes[0];
        }
        
        for(var i=0;i<xml.childNodes.length;i++){
            domChildNode=handleNode(xml.childNodes[i]);
            if(domChildNode!=null){
                if(firstNode==null){
                    domNode.appendChild(domChildNode);
                    firstNode=domChildNode;
                }
                else {
                    domNode.insertBefore(domChildNode,firstNode);
                }
                
            }
        }              
    }
    
    function getInsertAfter(domNode,xml){
        var domChildNode=null;
        var nextSibling=domNode.nextSibling;
        for(var i=0;i<xml.childNodes.length;i++){
            domChildNode=handleNode(xml.childNodes[i]);
            if(domChildNode!=null){
                if(nextSibling!=null) {
                    domNode.parentNode.insertBefore(domChildNode,nextSibling);
                }
                else {
                    domNode.parentNode.appendChild(domChildNode);
                }
            }
        }              
    }
    
    function getInsertBefore(domNode,xml){
        var domChildNode=null;
        for(var i=0;i<xml.childNodes.length;i++){
            domChildNode=handleNode(xml.childNodes[i]);
            if(domChildNode!=null) {
                domNode.parentNode.insertBefore(domChildNode,domNode);
            }
        }              
    }      
    
    function getReplace(domNode,xml){
        getInsertAfter(domNode,xml);
        domNode.parentNode.removeChild(domNode);
    }
    
    function getDelete(domNode) {
        domNode.parentNode.removeChild(domNode);
    }
    
    function getReplaceChildren(domNode,xml,doRemoveChildren) {
        var domChildNode=null;
        if(doRemoveChildren){
            while(domNode.childNodes.length >0){
                domNode.removeChild(domNode.childNodes[0]);
            }      
        }
        for(var i=0;i<xml.childNodes.length;i++){
            domChildNode=handleNode(xml.childNodes[i]);
            if(domChildNode!=null) {
                domNode.appendChild(domChildNode);
            }
        }              
    }
    
    function handleRedirect(xmlNode) {
        var targetUrl = xmlNode.getAttribute("targetUrl");
        window.location.replace(targetUrl);
    }
    
    function executeJavascript(xmlNode) {
        var scripts = xmlNode.getElementsByTagName("script");
        for (var i = 0; i < scripts.length; i++) {
            var script = scripts[i];
            if (script.getAttribute("type") == "text/javascript") {
                var js = script.firstChild.nodeValue;
                eval(js);
            }
        }
    }
    
    function cleanAttributeName(name) {
        if(isIE == false) {
            return;
        }
        
        // IE workaround to change cellspacing to cellSpacing, etc
        var cleanName = name.toLowerCase();
        if(cleanName == "cellspacing") {
            cleanName = "cellSpacing";
        }
        else if(cleanName == "cellpadding") {
            cleanName = "cellPadding";
        }
        else if(cleanName == "colspan") {
            cleanName = "colSpan";
        }
        else if(cleanName == "tabindex") {
            cleanName = "tabIndex";
        }
        else if(cleanName == "readonly") {
            cleanName = "readOnly";
        }
        return cleanName;
    }
    
}
/*
    json2.js
    2007-11-06

    Public Domain

    No warranty expressed or implied. Use at your own risk.

    See http://www.JSON.org/js.html

    This file creates a global JSON object containing two methods:

        JSON.stringify(value, whitelist)
            value       any JavaScript value, usually an object or array.

            whitelist   an optional that determines how object values are
                        stringified.

            This method produces a JSON text from a JavaScript value.
            There are three possible ways to stringify an object, depending
            on the optional whitelist parameter.

            If an object has a toJSON method, then the toJSON() method will be
            called. The value returned from the toJSON method will be
            stringified.

            Otherwise, if the optional whitelist parameter is an array, then
            the elements of the array will be used to select members of the
            object for stringification.

            Otherwise, if there is no whitelist parameter, then all of the
            members of the object will be stringified.

            Values that do not have JSON representaions, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped, in arrays will be replaced with null. JSON.stringify()
            returns undefined. Dates will be stringified as quoted ISO dates.

            Example:

            var text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'

        JSON.parse(text, filter)
            This method parses a JSON text to produce an object or
            array. It can throw a SyntaxError exception.

            The optional filter parameter is a function that can filter and
            transform the results. It receives each of the keys and values, and
            its return value is used instead of the original value. If it
            returns what it received, then structure is not modified. If it
            returns undefined then the member is deleted.

            Example:

            // Parse the text. If a key contains the string 'date' then
            // convert the value to a date.

            myData = JSON.parse(text, function (key, value) {
                return key.indexOf('date') >= 0 ? new Date(value) : value;
            });

    This is a reference implementation. You are free to copy, modify, or
    redistribute.

    Use your own copy. It is extremely unwise to load third party
    code into your pages.
*/

/*jslint evil: true */
/*extern JSON */

if (!this.JSON) {

    JSON = function () {

        function f(n) {    // Format integers to have at least two digits.
            return n < 10 ? '0' + n : n;
        }

        Date.prototype.toJSON = function () {

// Eventually, this method will be based on the date.toISOString method.

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };


        var m = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

        function stringify(value, whitelist) {
            var a,          // The array holding the partial texts.
                i,          // The loop counter.
                k,          // The member key.
                l,          // Length.
                r = /["\\\x00-\x1f\x7f-\x9f]/g,
                v;          // The member value.

            switch (typeof value) {
            case 'string':

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe sequences.

                return r.test(value) ?
                    '"' + value.replace(r, function (a) {
                        var c = m[a];
                        if (c) {
                            return c;
                        }
                        c = a.charCodeAt();
                        return '\\u00' + Math.floor(c / 16).toString(16) +
                                                   (c % 16).toString(16);
                    }) + '"' :
                    '"' + value + '"';

            case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':
                return String(value);

            case 'object':

// Due to a specification blunder in ECMAScript,
// typeof null is 'object', so watch out for that case.

                if (!value) {
                    return 'null';
                }

// If the object has a toJSON method, call it, and stringify the result.

                if (typeof value.toJSON === 'function') {
                    return stringify(value.toJSON());
                }
                a = [];
                if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length'))) {

// The object is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                    l = value.length;
                    for (i = 0; i < l; i += 1) {
                        a.push(stringify(value[i], whitelist) || 'null');
                    }

// Join all of the elements together and wrap them in brackets.

                    return '[' + a.join(',') + ']';
                }
                if (whitelist) {

// If a whitelist (array of keys) is provided, use it to select the components
// of the object.

                    l = whitelist.length;
                    for (i = 0; i < l; i += 1) {
                        k = whitelist[i];
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                } else {

// Otherwise, iterate through all of the keys in the object.

                    for (k in value) {
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                }

// Join all of the member texts together and wrap them in braces.

                return '{' + a.join(',') + '}';
            }
        }

        return {
            stringify: stringify,
            parse: function (text, filter) {
                var j;

                function walk(k, v) {
                    var i, n;
                    if (v && typeof v === 'object') {
                        for (i in v) {
                            if (Object.prototype.hasOwnProperty.apply(v, [i])) {
                                n = walk(i, v[i]);
                                if (n !== undefined) {
                                    v[i] = n;
                                }
                            }
                        }
                    }
                    return filter(k, v);
                }


// Parsing happens in three stages. In the first stage, we run the text against
// regular expressions that look for non-JSON patterns. We are especially
// concerned with '()' and 'new' because they can cause invocation, and '='
// because it can cause mutation. But just to be safe, we want to reject all
// unexpected forms.

// We split the first stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace all backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

                if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the second stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                    j = eval('(' + text + ')');

// In the optional third stage, we recursively walk the new structure, passing
// each name/value pair to a filter function for possible transformation.

                    return typeof filter === 'function' ? walk('', j) : j;
                }

// If the text is not JSON parseable, then a SyntaxError is thrown.

                throw new SyntaxError('parseJSON');
            }
        };
    }();
}

String.prototype.trim = function() {
    //skip leading and trailing whitespace
    //and return everything in between
    var x=this;
    x=x.replace(/^\s*(.*)/, "$1");
    x=x.replace(/(.*?)\s*$/, "$1");
    return x;
};


document.getElementsByMatchingId = function(matchingId) {
    var allElements = document.all ? document.all : document.getElementsByTagName('*');
    var matchingElements = new Array();
    for (var i = 0; i < allElements.length; i++) {
        var currentElement = allElements[i];
        if (currentElement.nodeType == 1) {
            var id = currentElement.getAttribute("id");
            if (id != null && id != "") {
                if (id.indexOf("_") == (id.length - 1)) {
                    var pattern = "^" + id.replace(/_$/, ".*");
                    var rexp = new RegExp(pattern);
                    if (rexp.test(matchingId)) {
                        matchingElements.push(currentElement);
                    }
                } else if (id == matchingId) {
                    matchingElements.push(currentElement);
                }
            }
        }
    }
    return matchingElements;
};