// ========================== sendEmail ===================
var sendform;

function sendEmail(frm){
    sendform = frm
    
    var elements = frm.elements;
    var vars = new Array();
    var order = '';
    
    for (var i=0; i < elements.length; i++){
        var name, value, type;
        if (elements[i].id)
            name =elements[i].id;
        else if (elements[i].name)
            name =elements[i].name;
        else
            name = 'param[' + i + ']';
        
        value = getElementValue(elements[i]).replace(/^\s*|\s*$/g,"");
        type = elements[i].type;
        
        if (type != 'button' && (type != 'hidden' || name == 'sendto') && type != 'submit' && value != null && value != ''){
            vars[name] = value; 
            if (order.length > 0) 
                order += ';';
            if  (name != 'sendto')
            order += name;
        }
    }

    vars['order'] = order;
    ajaxCaller.postForXML("/sendmail/sendmail.jsp", vars, callback);
    
    return false;
}  


function callback(xml, headers, callingContext){
    
    var status = xml.getElementsByTagName("status")[0].firstChild.nodeValue;
    var message = xml.getElementsByTagName("message")[0].firstChild.nodeValue;
    if (status.replace(/^\s*|\s*$/g,"") == 'ok'){
        for (var i=0; i < sendform.elements.length; i++){
            var type = sendform.elements[i].type;
        
            if (type != 'button' && type != 'hidden' && type != 'submit'){
               value = setElementValue(sendform.elements[i], '');
            }
        }
    }
    alert(message);
    
}

function getElementValue(formElement) {
    if(formElement.length != null) var type = formElement[0].type;
    if((typeof(type) == 'undefined') || (type == 0)) var type = formElement.type;
    
    switch(type) {
        case 'undefined': return;
        
        case 'radio':
            for(var x=0; x < formElement.length; x++) 
                if(formElement[x].checked == true)
                    return formElement[x].value;
            
        case 'select-multiple':
            var myArray = new Array();
            for(var x=0; x < formElement.length; x++) 
                if(formElement[x].selected == true)
                    myArray[myArray.length] = formElement[x].value;
            return myArray;
            
        case 'checkbox': return formElement.checked;
        
        default: return formElement.value;
    }
}

function setElementValue(formElement, value) {
    switch(formElement.type) {
        case 'undefined': return;
        case 'radio': formElement.checked = value; break;
        case 'checkbox': formElement.checked = value; break;
        case 'select-one': formElement.selectedIndex = value; break;
        
        case 'select-multiple':
            for(var x=0; x < formElement.length; x++) 
                formElement[x].selected = value[x];
            break;
            
        default: formElement.value = value; break;
    }
}

// =============================================================================            
var ajaxCaller = {
    
    shouldDebug: false,
    shouldEscapeVars: false,
    shouldMakeHeaderMap: true,
    
    calls : new Array(),
    pendingResponseCount : 0,
    
    /**************************************************************************
     PUBLIC METHODS
     *************************************************************************/
    
    getXML: function(url, callbackFunction) {
        this.get(url, null, callbackFunction, true, null);
    },
    
    getPlainText: function(url, callbackFunction) {
        this.get(url, null, callbackFunction, false, null);
    },
    
    postForPlainText: function(url, vars, callbackFunction) {
        this.postVars(url, vars, null, callbackFunction, false,
        null, "POST", null, null, null);
    },
    
    postForXML: function(url, vars, callbackFunction) {
        this.postVars(url, vars, null, callbackFunction, true,
        null, "POST", null, null, null);
    },
    
    get: function(url, urlVars, callbackFunction, expectingXML, callingContext) {
        this._callServer(url, urlVars, callbackFunction, expectingXML,
        callingContext, "GET", null, null, null);
    },
    
    postVars:
        function(url, bodyVars, optionalURLVars, callbackFunction, expectingXML,
        callingContext) {
            this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
            callingContext, "POST", bodyVars, null, null);
        },
        
        postBody:
            function(url, optionalURLVars, callbackFunction, expectingXML,
            callingContext, bodyType, body) {
                this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
                callingContext, "POST", null, bodyType, body);
            },
            
            putBody:
                function(url, optionalURLVars, callbackFunction, expectingXML,
                callingContext, bodyType, body) {
                    this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
                    callingContext, "PUT", null, bodyType, body);
                },
                
                options:
                    function(url, optionalURLVars, callbackFunction, expectingXML,
                    callingContext, bodyType, body) {
                        this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
                        callingContext, "OPTIONS", null, bodyType, body);
                    },
                    
                    trace:
                        function(url, optionalURLVars, callbackFunction, expectingXML,
                        callingContext, bodyType, body) {
                            this._debug("trace");
                            this._callServer(url, optionalURLVars, callbackFunction, expectingXML,
                            callingContext, "TRACE", null, bodyType, body);
                        },
                        
                        deleteIt: function(url, urlVars, callbackFunction,
                        expectingXML, callingContext) {
                            this._callServer(url, urlVars, callbackFunction, expectingXML,
                            callingContext, "DELETE", null, null, null);
                        },
                        
                        head: function(url, urlVars, callbackFunction, expectingXML, callingContext) {
                            this._callServer(url, urlVars, callbackFunction, expectingXML,
                            callingContext, "HEAD", null, null, null);
                        },
                        
                        /**************************************************************************
     PRIVATE METHODS
                         *************************************************************************/
                        
                        _callServer: function(url, urlVars, callbackFunction, expectingXML,
                        callingContext, requestMethod, bodyVars,
                        explicitBodyType, explicitBody) {
                            
                            if (urlVars==null) {
                                urlVars = new Array();
                            }
                            
                            this._debug("_callServer() called. About to request URL\n"
                            + "call key: [" + this.calls.length + "]\n"
                            + "url: [" + url + "]\n"
                            + "callback function: [" + callbackFunction + "]\n"
                            + "treat response as xml?: [" + expectingXML + "]\n"
                            + "Request method?: [" + requestMethod + "]\n"
                            + "calling context: [" + callingContext + "]\n"
                            + "explicit body type: [" + explicitBodyType + "]\n"
                            + "explicit body: [" + explicitBody + "]\n"
                            + "urlVars: [" + util.describe(urlVars) + "]\n"
                            + "bodyVars: [" + util.describe(bodyVars) + "]"
                            );
                            
                            
                            var xReq = this._createXMLHttpRequest();
                            xReq.onreadystatechange = function() {
                                ajaxCaller._onResponseStateChange(call);
                            }
                            
                            var call = {xReq: xReq,
                            callbackFunction: callbackFunction,
                            expectingXML: expectingXML,
                            callingContext: callingContext,
                            url: url};
                            
                            if (urlVars!=null) {
                                var urlVarsString = this._createHTTPVarSpec(urlVars);
                                if (urlVarsString.length > 0) { // TODO check if appending with & instead
                                    url += "?" + urlVarsString;
                                }
                            }
                            
                            xReq.open(requestMethod, url, true);
                            
                            if (   requestMethod=="GET"
                            || requestMethod=="HEAD"
                            || requestMethod=="DELETE") {
                                this._debug("Body-less request to URL " + url);
                                xReq.send(null);
                                return;
                            }
                            
                            if (   requestMethod=="POST"
                            || requestMethod=="PUT"
                            || requestMethod=="OPTIONS"
                            || requestMethod=="TRACE") {
                                bodyType = null;
                                body = null;
                                if (explicitBodyType==null) { // It's a form
                                    bodyType = 'application/x-www-form-urlencoded; charset=UTF-8';
                                    body = this._createHTTPVarSpec(bodyVars);
                                } else {
                                    bodyType = explicitBodyType;
                                    body = explicitBody;
                                }
                                this._debug("Content-Type: [" + bodyType + "]\nBody: [" + body + "].");
                                xReq.setRequestHeader('Content-Type',  bodyType);
                                xReq.send(body);
                                return;
                            }
                            
                            this._debug("ERROR: Unknown Request Method: " + requestMethod);
                            
                            
                        },
                        
                        // The callback of xmlHttpRequest is a dynamically-generated function which
                        // immediately calls this function.
                        _onResponseStateChange: function(call) {
                            
                            xReq = call.xReq;
                            
                            if (xReq.readyState < 4) { //Still waiting
                                return;
                            }
                            
                            if (xReq.readyState == 4) { //Transmit to actual callback
                                this._debug("Call " + util.describe(call)
                                + " with context [" + call.callingContext+"]"
                                + " to " + call.url + " has returned.");
                                callbackFunction = call.callbackFunction;
                                if (!callbackFunction) { // Maybe still loading, e.g. in another JS file
                                    setTimeout(function() {
                                        _onResponseStateChange(call);
                                    }, 100);
                                }
                                var content = call.expectingXML ? xReq.responseXML : xReq.responseText;
                                responseHeaders = xReq.getAllResponseHeaders();
                                headersForCaller = this.shouldMakeHeaderMap ?
                                    this._createHeaderMap(responseHeaders) : responseHeaders;
                                    callbackFunction(content, headersForCaller, call.callingContext);
                            }
                            
                            call = null; // Technically the responsibility of GC
                            this.pendingResponseCount--;
                            
                        },
                        
                        // Browser-agnostic factory function
                        _createXMLHttpRequest: function() {
                            if (window.XMLHttpRequest) {
                                return new XMLHttpRequest();
                            } else if (window.ActiveXObject) {
                                return new ActiveXObject('Microsoft.XMLHTTP')
                            } else {
                                _error("Could not create XMLHttpRequest on this browser");
                                return null;
                            }
                        },
                        
                        _createHTTPVarSpec: function(vars) {
                            var varsString = "";
                            for( key in vars ) {
                                var value = vars[key];
                                if (this.shouldEscapeVars) {
                                    escapePlusRE =  new RegExp("\\\+");
                                    value = value.replace(escapePlusRE, "%2B");
                                }
                                varsString += '&' + key + '=' + value;
                            }
                            if (varsString.length > 0) {
                                varsString = varsString.substring(1); // chomp initial '&'
                            }
                            this._debug("Built var String: " + varsString)
                            return varsString;
                        },
                        
                        /* Creates associative array from header type to header */
                        _createHeaderMap: function(headersText) {
                            extractedHeaders = headersText.split("\n");
                            delete extractedHeaders[extractedHeaders.length]; // Del blank line at end
                            headerMap = new Array();
                            for (i=0; i<extractedHeaders.length-2; i++) {
                                head = extractedHeaders[i];
                                fieldNameEnding = head.indexOf(":");
                                field = head.substring(0, fieldNameEnding);
                                value = head.substring(fieldNameEnding + 2, head.length);
                                value = value.replace(/\s$/, "");
                                headerMap[field] = value;
                            }
                            return headerMap;
                        },
                        
                        _debug: function(message) {
                            if (this.shouldDebug) {
                                alert("AjaxJS Message:\n\n" + message);
                            }
                        },
                        
                        _error: function(message) {
                            if (this.shouldDebug) {
                                alert("AjaxJS ERROR:\n\n" + message);
                            }
                        }
                        
};

//========================= util.js


var util = {
    
    shouldDebug: false,
    
    // Note: Will fail in pathological cases (where the members contain
    // strings similar to describe() result).
    membersEqual: function(array1, array2) {
        return util.describe(array1)==util.describe(array2);
    },
    
    describe: function(obj) {
        if (obj==null) { return null; }
        switch(typeof(obj)) {
            case 'object': {
                var message = "";
                for (key in obj) {
                    message += ", [" + key + "]: [" + obj[key] + "]";
                }
                if (message.length > 0) {
                    message = message.substring(2); // chomp initial ', '
                }
                return message;
            }
            default: return "" + obj;
        }
    },
    
    debug: function(message) {
        if (this.shouldDebug) {
            alert("AjaxJS Message:\n\n" + message);
        }
    },
    
    error: function(message) {
        if (this.shouldDebug) {
            alert("AjaxJS ERROR:\n\n" + message);
        }
    },
    
    // trim() From Shawn Milo
    // https://lists.latech.edu/pipermail/javascript/2004-May/007567.html
    trim: function(str) {
        return str.replace(/^(\s+)?(.*\S)(\s+)?$/, '$2');
    },
    
    strip: function(str) {
        return str.replace(/\s+/, "");
    }
    
}

function $() {
    
    var elements = new Array();
    
    for (var i = 0; i < arguments.length; i++) {
        
        var element = arguments[i];
        
        if (typeof element == 'string') {
            if (document.getElementById) {
                element = document.getElementById(element);
            } else if (document.all) {
                element = document.all[element];
            }
        }
        
        elements.push(element);
        
    }
    
    if (arguments.length == 1 && elements.length > 0) {
        return elements[0];
    } else {
        return elements;
    }
}

function $C(elType) {
    return document.createElement(elType);
}

// From prototype library. Try.these(f1, f2, f3);
var Try = {
    these: function() {
        var returnValue;
        for (var i = 0; i<arguments.length; i++) {
            var lambda = arguments[i];
            try {
                returnValue = lambda();
                break;
            } catch (e) {}
        }
        return returnValue;
    }
}

function getElementsByClassName(classname) {
    var a = [];
    var re = new RegExp('\\b' + classname + '\\b');
    var els = document.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}

function extractIFrameBody(iFrameEl) {
    
    var doc = null;
    if (iFrameEl.contentDocument) { // For NS6
        doc = iFrameEl.contentDocument; 
    } else if (iFrameEl.contentWindow) { // For IE5.5 and IE6
        doc = iFrameEl.contentWindow.document;
    } else if (iFrameEl.document) { // For IE5
        doc = iFrameEl.document;
    } else {
        alert("Error: could not find sumiFrame document");
        return null;
    }
    return doc.body;
    
}



/* function getElementsByClassName(needle) {
 
 
 
  var xpathResult = document.evaluate('//*[@class = needle]', document, null, 0, null);
  var outArray = new Array();
  while ((outArray[outArray.length] = xpathResult.iterateNext())) {
  }
  return outArray;
}
 */

/*
  function acceptNode(node) {
    if (node.hasAttribute("class")) {
      var c = " " + node.className + " ";
       if (c.indexOf(" " + needle + " ") != -1)
         return NodeFilter.FILTER_ACCEPT;
    }
    return NodeFilter.FILTER_SKIP;
  }
 
  var treeWalker = document.createTreeWalker(document.documentElement,
                                             NodeFilter.SHOW_ELEMENT,
                                             acceptNode,
                                             true);
  var outArray = new Array();
  if (treeWalker) {
    var node = treeWalker.nextNode();
    while (node) {
      outArray.push(node);
      node = treeWalker.nextNode();
    }
  }
  return outArray;
}
 
 */
///////////////////////////////////////////////////////////////////////////////
// Used for pattern-specific demos.
///////////////////////////////////////////////////////////////////////////////

var DELAY = 1000;
var steps = 0;
function andThen(action) {
    var delayTime = (++steps * DELAY);
    setTimeout(action, delayTime);
}

function log(message) {
    $("log").innerHTML += message + "<br/>";
}

function createXMLHttpRequest() {
    try { return new ActiveXObject("Msxml2.XMLHTTP");    } catch(e) {}
    try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
    try { return new XMLHttpRequest();                   } catch(e) {}
    alert("XMLHttpRequest not supported");
    return null;
}




