function empty (v)
    {
    return null === v || false === v || "" === v || undefined === v || typeof v == undefined || v.length == 0;
    }

function trim(str, chars) {
    return ltrim(rtrim(str, chars), chars);
}
 
function ltrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}
 
function rtrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}

function prepareFormForSubmit (form, evt)
    {
    if (evt.shiftKey)
        form.target='_blank';
    else
        form.target='_self';
    }

function getXMLHTTP()
    {
    if (typeof XMLHttpRequest == "undefined") {
      XMLHttpRequest = function() {
        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
          catch(e) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
          catch(e) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP"); }
          catch(e) {}
        try { return new ActiveXObject("Microsoft.XMLHTTP"); }
          catch(e) {}
        throw new Error("This browser does not support XMLHttpRequest.");
      };
    }
    
    return new XMLHttpRequest();
    }

function addEvent (target, eventName, handler)
    {
    if (target.addEventListener)
      target.addEventListener (eventName, handler, false);
    else if (target.attachEvent)
      target.attachEvent ("on" + eventName, handler);
    else
      target["on" + eventName] = handler;
    }

function fireEvent (target, eventName, eventClass)
    {
    if (document.all)
        target.fireEvent ("on" + eventName);
    else
        {
        if (undefined === eventClass)
            eventClass = "HTMLEvents";
        var eventInstance = document.createEvent (eventClass);
        switch (eventClass)
            {
            case "HTMLEvents":
                eventInstance.initEvent (eventName, true, true);
                break;
            case "UIEvents":
                eventInstance.initUIEvent (eventName, true, true, window, null);
                break;
            case "HTMLEvents":
                eventInstance.initMouseEvent (eventName, true, true, window /* some value missing */);
                break;
            }
        target.dispatchEvent (eventInstance);
        }
    }

function showWebServiceRequestError (request)
    {
    try
        {
        var status = "HTTP error received (" + request.status;
        if (request.statusText)
            status += ": " + request.statusText;
        status += ")" + ")\n\n";
        alert (status);
        }
    catch (e)
        {
        window.status = e.message;
        }
    }

function handleServiceResponse (request, successCallback)
    {
    // window.status = "State: " + request.readyState;
    if (request.readyState == 4)
        {
        // window.status = window.status + " - " + request.status;
        if (200 == request.status)
            {
            if (!request.responseXML || !request.responseXML.documentElement || "Results" != request.responseXML.documentElement.nodeName)
                {
                if (!empty (request.responseText))
                    {
                    var wnd = window.open ();
                    if (undefined === wnd || null === wnd)
                        window.status = "error";
                    else
                        {
                        wnd.document.writeln (request.responseText);
                        if (empty (wnd.document.title))
                            wnd.document.title = "Error";
                        wnd.document.close();
                        }
                    }
                else
                    window.status = "unexpected error";

                return;
                }

            var results = request.responseXML.getElementsByTagName ("Error");
            if (results && results.length > 0)
                {
                var errors = new Array ();
                for (var i = 0; i < results.length; i++)
                    errors.push (results[i].firstChild.data);
                alert (errors.join ("\n"));
                }
            else
                {
                successCallback (request);
                }
            }
        else
            {
            showWebServiceRequestError (request);
            }
        }
    }

function getXmlSubnodeText (node, subnodeName)
    {
    if (empty (node))
        return null;
    var subnodes = node.getElementsByTagName (subnodeName);
    if (empty (subnodes))
        return null;
    var subnode = subnodes[0];
    if (empty (subnode.firstChild))
        return null;
    return subnode.firstChild.data;
    }

function getAbsolutePosition (element)
    {
    if (empty (element))
        return null;
    var topValue = 0;
    var leftValue = 0;
    var current = element;
    while (current)
        {
        leftValue += current.offsetLeft;
        topValue += current.offsetTop;
        current = current.offsetParent;
        }

    return { left:leftValue, right:leftValue + element.offsetWidth, top: topValue, bottom: topValue + element.offsetHeight};
    }

function eventCancel (e)
    {
    if (!e)
        {
        if (window.event)
            e = window.event;
        else
            return;
        }

    if (e.cancelBubble != null)
        e.cancelBubble = true;
    if (e.stopPropagation)
        e.stopPropagation();
    if (e.preventDefault)
        e.preventDefault();
    if (window.event)
        e.returnValue = false;
    if (e.cancel != null)
        e.cancel = true;
    }

function extractHtmlFromXmlResponse (request)
    {
    var results = request.responseXML.getElementsByTagName ("Result");
    var html = "";
    for (var i = 0; i < results.length; i++)
        html += getXmlSubnodeText (results[i], "html");
    return html;
    }

function showPreview (html, closeButtonText)
    {
    var previewBody = document.createElement ("div");
    previewBody.className = "previewbody";
    var container = document.createElement ("div");
    container.className = "previewcontainer";
    var innerContainer = document.createElement ("div");
    innerContainer.className = "previewinner";
    innerContainer.innerHTML = html;

    var closeButtonContainer = document.createElement ("div");
    closeButtonContainer.className = "previewclose";
    var closeButton = document.createElement ("input");
    closeButton.type = "button";
    closeButton.value = closeButtonText;
    closeButton.className = "previewclose";
    closeButtonContainer.appendChild (closeButton);

    previewBody.appendChild (container);
    container.appendChild (innerContainer);
    container.appendChild (closeButtonContainer);
    
    var closeFn = function ()
        {
        document.body.removeChild (previewBody);
        previewBody = null;
        };

    addEvent (previewBody, "click", closeFn);
    addEvent (closeButton, "click", closeFn);
    
    document.body.appendChild (previewBody);
    }

function toElement (html)
    {
    var div = document.createElement('div');
    div.innerHTML = html;
    var el = div.firstChild;
    return div.removeChild(el);
    }
