// See: http://www.crockford.com/javascript/jslint.html
/*global DWREngine, Option, alert, document, setTimeout, window */

/**
 * Declare a constructor function to which we can add real functions.
 * @constructor
 */
function DWRUtil() { }

////////////////////////////////////////////////////////////////////////////////
// The following functions are described in util-compat.html

/**
 * Enables you to react to return being pressed in an input
 * For example:
 * <code>&lt;input type="text" onkeypressed="DWRUtil.onReturn(event, methodName)"/&gt;</code>
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param event The event object for Netscape browsers
 * @param action Method name to execute when return is pressed
 */
DWRUtil.onReturn = function(event, action)
{
    if (!event)
    {
        event = window.event;
    }

    if (event && event.keyCode && event.keyCode == 13)
    {
        action();
    }
};

/**
 * Select a specific range in a text box.
 * This is useful for 'google suggest' type functionallity.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The id of the text input element or the HTML element itself
 * @param start The beginning index
 * @param end The end index 
 */
DWRUtil.selectRange = function(ele, start, end)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("selectRange() can't find an element with id: " + orig + ".");
        return;
    }

    if (ele.setSelectionRange)
    {
        ele.setSelectionRange(start, end);
    }
    else if (ele.createTextRange)
    {
        var range = ele.createTextRange();
        range.moveStart("character", start);
        range.moveEnd("character", end - ele.value.length);
        range.select();
    }

    ele.focus();
};

////////////////////////////////////////////////////////////////////////////////
// The following functions are described in util-general.html

/**
 * Find the element in the current HTML document with the given id, or if more
 * than one parameter is passed, return an array containing the found elements.
 * Any non-string arguments are left as is in the reply.
 * This function is inspired by the prototype library however it probably works
 * on more browsers than the original.
 * @see http://www.getahead.ltd.uk/dwr/util-general.html
 */
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];
            }
        }

        if (arguments.length == 1) 
        {
            return element;
        }

        elements.push(element);
    }

    return elements;
}

/**
 * A better toString than the default for an Object
 * @param data The object to describe
 * @param level 0 = Single line of debug, 1 = Multi-line debug that does not
 *              dig into child objects, 2 = Multi-line debug that digs into the
 *              2nd layer of child objects
 * @param depth How much do we indent this item?
 * @see http://www.getahead.ltd.uk/dwr/util-general.html
 */
DWRUtil.toDescriptiveString = function(data, level, depth)
{
    var reply = "";
    var i = 0;
    var value;

    if (level == null)
    {
        level = 0;
    }

    if (depth == null)
    {
        depth = 0;
    }

    if (data == null)
    {
        return "null";
    }

    if (DWRUtil._isArray(data))
    {
        reply = "[";
        if (level != 0)
        {
            reply += "\n";
        }

        for (i = 0; i < data.length; i++)
        {
            try
            {
                obj = data[i];

                if (obj == null || typeof obj == "function")
                {
                    continue;
                }
                else if (typeof obj == "object")
                {
                    if (level > 0)
                    {
                        value = DWRUtil.toDescriptiveString(obj, level - 1, depth + 1);
                    }
                    else
                    {
                        value = DWRUtil._detailedTypeOf(obj);
                    }
                }
                else
                {
                    value = "" + obj;
                    value = value.replace(/\/n/g, "\\n");
                    value = value.replace(/\/t/g, "\\t");
                }
            }
            catch (ex)
            {
                value = "" + ex;
            }

            if (level == 0 && value.length > 13)
            {
                value = value.substring(0, 10) + "...";
            }

            reply += value;
            reply += ", ";

            if (level != 0)
            {
                reply += "\n";
            }

            if (level == 0 && i > 5)
            {
                reply += "...";
                break;
            }
        }
        reply += "]";

        return reply;
    }

    if (typeof data == "string" || typeof data == "number" || DWRUtil._isDate(data))
    {
        return data.toString();
    }

    if (typeof data == "object")
    {
        var typename = DWRUtil._detailedTypeOf(data);
        if (typename != "Object")
        {
            reply = typename + " ";
        }

        if (level != 0)
        {
            reply += DWRUtil._indent(level, depth);
        }
        reply += "{";
        if (level != 0)
        {
            reply += "\n";
        }

        var isHtml = DWRUtil._isHTMLElement(data);

        for (var prop in data)
        {
            if (isHtml)
            {
                if (prop.toUpperCase() == prop || prop == "title" ||
                    prop == "lang" || prop == "dir" || prop == "className" ||
                    prop == "form" || prop == "name" || prop == "prefix" ||
                    prop == "namespaceURI" || prop == "nodeType" ||
                    prop == "firstChild" || prop == "lastChild" ||
                    prop.match(/^offset/))
                {
                    // HTML nodes have far too much stuff. Chop out the constants
                    continue;
                }
            }

            value = "";

            try
            {
                obj = data[prop];

                if (obj == null || typeof obj == "function")
                {
                    continue;
                }
                else if (typeof obj == "object")
                {
                    if (level > 0)
                    {
                        value = "\n";
                        value += DWRUtil._indent(level, depth + 2);
                        value = DWRUtil.toDescriptiveString(obj, level - 1, depth + 1);
                    }
                    else
                    {
                        value = DWRUtil._detailedTypeOf(obj);
                    }
                }
                else
                {
                    value = "" + obj;
                    value = value.replace(/\/n/g, "\\n");
                    value = value.replace(/\/t/g, "\\t");
                }
            }
            catch (ex)
            {
                value = "" + ex;
            }

            if (level == 0 && value.length > 13)
            {
                value = value.substring(0, 10) + "...";
            }

            if (level != 0)
            {
                reply += DWRUtil._indent(level, depth + 1);
            }
            reply += prop;
            reply += ":";
            reply += value;
            reply += ", ";

            if (level != 0)
            {
                reply += "\n";
            }

            i++;
            if (level == 0 && i > 5)
            {
                reply += "...";
                break;
            }
        }

        reply += DWRUtil._indent(level, depth);
        reply += "}";

        return reply;
    }

    return data.toString();
};

/**
 * Indenting for DWRUtil.toDescriptiveString
 * @private
 */
DWRUtil._indent = function(level, depth)
{
    var reply = "";
    if (level != 0)
    {
        for (var j = 0; j < depth; j++)
        {
            reply += "--";
        }
        reply += " ";
    }
    return reply;
};

/**
 * Setup a GMail style loading message.
 * @see http://www.getahead.ltd.uk/dwr/util-general.html
 */
DWRUtil.useLoadingMessage = function()
{
    var disabledZone = document.createElement('div');
    disabledZone.setAttribute('id', 'disabledZone');
    disabledZone.style.position = "absolute";
    disabledZone.style.zIndex = "1000";
    disabledZone.style.left = "0px";
    disabledZone.style.top = "0px";
    disabledZone.style.width = "100%";
    disabledZone.style.height = "100%";
    document.body.appendChild(disabledZone);

    var messageZone = document.createElement('div');
    messageZone.setAttribute('id', 'messageZone');
    messageZone.style.position = "absolute";
    messageZone.style.top = "0px";
    messageZone.style.right = "0px";
    messageZone.style.background = "red";
    messageZone.style.color = "white";
    messageZone.style.fontFamily = "Arial,Helvetica,sans-serif";
    messageZone.style.padding = "4px";
    disabledZone.appendChild(messageZone);

    var text = document.createTextNode('Loading.....');
    messageZone.appendChild(text);

    $('disabledZone').style.visibility = 'hidden';

    DWREngine.setPreHook(function() { $('disabledZone').style.visibility = 'visible'; });
    DWREngine.setPostHook(function() { $('disabledZone').style.visibility = 'hidden'; });
};

////////////////////////////////////////////////////////////////////////////////
// The following functions are described in util-simple.html

/**
 * Set the value for the given id to the specified val.
 * This method works for selects (where the option with a matching value and
 * not text is selected), input elements (including textareas) divs and spans.
 * @see http://www.getahead.ltd.uk/dwr/util-simple.html
 * @param ele The id of the element or the HTML element itself
 */
DWRUtil.setValue = function(ele, val)
{
    if (val == null)
    {
        val = "";
    }

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("setValue() can't find an element with id: " + orig + ".");
        return;
    }

    if (DWRUtil._isHTMLElement(ele, "select"))
    {
        // search through the values
        var found  = false;
        var i;

        for (i = 0; i < ele.options.length; i++)
        {
            if (ele.options[i].value == val)
            {
                ele.options[i].selected = true;
                found = true;
            }
            else
            {
                ele.options[i].selected = false;
            }
        }

        // If that fails then try searching through the visible text
        if (found)
        {
            return;
        }

        for (i = 0; i < ele.options.length; i++)
        {
            if (ele.options[i].text == val)
            {
                ele.options[i].selected = true;
                break;
            }
        }

        return;
    }

    if (DWRUtil._isHTMLElement(ele, "input"))
    {
        switch (ele.type)
        {
        case "checkbox":
        case "check-box":
        case "radio":
            ele.checked = (val == true);
            return;

        default:
            ele.value = val;
            return;
        }
    }

    if (DWRUtil._isHTMLElement(ele, "textarea"))
    {
        ele.value = val;
        return;
    }

    ele.innerHTML = val;
};

/**
 * The counterpart to setValue() - read the current value for a given element.
 * This method works for selects (where the option with a matching value and
 * not text is selected), input elements (including textareas) divs and spans.
 * @see http://www.getahead.ltd.uk/dwr/util-simple.html
 * @param ele The id of the element or the HTML element itself
 */
DWRUtil.getValue = function(ele)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("getValue() can't find an element with id: " + orig + ".");
        return;
    }

    if (DWRUtil._isHTMLElement(ele, "select"))
    {
        // This is a bit of a scam because it assumes single select
        // but I'm not sure how we should treat multi-select.
        var sel = ele.selectedIndex;
        if (sel != -1)
        {
            var reply = ele.options[sel].value;
            if (reply == null || reply == "")
            {
                reply = ele.options[sel].text;
            }

            return reply;
        }
        else
        {
            return "";
        }
    }

    if (DWRUtil._isHTMLElement(ele, "input"))
    {
        switch (ele.type)
        {
        case "checkbox":
        case "check-box":
        case "radio":
            return ele.checked;

        default:
            return ele.value;
        }
    }

    if (DWRUtil._isHTMLElement(ele, "textarea"))
    {
        return ele.value;
    }

    return ele.innerHTML;
};

/**
 * getText() is like getValue() with the except that it only works for selects
 * where it reads the text of an option and not it's value.
 * @see http://www.getahead.ltd.uk/dwr/util-simple.html
 * @param ele The id of the element or the HTML element itself
 */
DWRUtil.getText = function(ele)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("getText() can't find an element with id: " + orig + ".");
        return;
    }

    if (!DWRUtil._isHTMLElement(ele, "select"))
    {
        //alert("getText() can only be used with select elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele) + " from  id: " + orig + ".");
        return;
    }

    // This is a bit of a scam because it assumes single select
    // but I'm not sure how we should treat multi-select.
    var sel = ele.selectedIndex;
    if (sel != -1)
    {
        return ele.options[sel].text;
    }
    else
    {
        return "";
    }
};

/**
 * Given a map, call setValue() for all the entries in the map using the key
 * of each entry as an id.
 * @see http://www.getahead.ltd.uk/dwr/util-simple.html
 * @param map The map of values to set to various elements
 */
DWRUtil.setValues = function(map)
{
    for (var property in map)
    {
        var ele = $(property);
        if (ele != null)
        {
            var value = map[property];
            DWRUtil.setValue(property, value);
        }
    }
};

/**
 * Given a map, call getValue() for all the entries in the map using the key
 * of each entry as an id.
 * @see http://www.getahead.ltd.uk/dwr/util-simple.html
 * @param map The map of values to set to various elements
 */
DWRUtil.getValues = function(map)
{
    for (var property in map)
    {
        var ele = $(property);
        if (ele != null)
        {
            map[property] = DWRUtil.getValue(property);
        }
    }
};

////////////////////////////////////////////////////////////////////////////////
// The following functions are described in util-list.html

/**
 * Add options to a list from an array or map.
 * DWRUtil.addOptions has 5 modes:
 * <p><b>Array</b><br/>
 * DWRUtil.addOptions(selectid, array) and a set of options are created with the
 * text and value set to the string version of each array element.
 * </p>
 * <p><b>Array of objects, using option text = option value</b><br/>
 * DWRUtil.addOptions(selectid, data, prop) creates an option for each array
 * element, with the value and text of the option set to the given property of
 * each object in the array.
 * </p>
 * <p><b>Array of objects, with differing option text and value</b><br/>
 * DWRUtil.addOptions(selectid, array, valueprop, textprop) creates an option
 * for each object in the array, with the value of the option set to the given
 * valueprop property of the object, and the option text set to the textprop
 * property.
 * </p>
 * <p><b>Map (object)</b><br/>
 * DWRUtil.addOptions(selectid, map, reverse) creates an option for each
 * property. The property names are used as option values, and the property
 * values are used as option text, which sounds wrong, but is actually normally
 * the right way around. If reverse evaluates to true then the property values
 * are used as option values.
 * <p><b>ol or ul list</b><br/>
 * DWRUtil.addOptions(ulid, array) and a set of li elements are created with the
 * innerHTML set to the string value of the array elements. This mode works
 * with ul and ol lists.
 * </p>
 * @see http://www.getahead.ltd.uk/dwr/util-list.html
 * @param ele The id of the list element or the HTML element itself
 * @param data An array or map of data items to populate the list
 * @param valuerev (optional) If data is an array of objects, an optional
 *        property name to use for option values. If the data is a map then this
 *        boolean property allows you to swap keys and values.
 * @param textprop (optional) Only for use with arrays of objects - an optional
 *        property name for use as the text of an option.
 */
DWRUtil.addOptions = function(ele, data, valuerev, textprop)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("addOptions() can't find an element with id: " + orig + ".");
        return;
    }

    var useOptions = DWRUtil._isHTMLElement(ele, "select");
    var useLi = DWRUtil._isHTMLElement(ele, ["ul", "ol"]);

    if (!useOptions && !useLi)
    {
        //alert("fillList() can only be used with select elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
        return;
    }

    // Bail if we have no data
    if (data == null)
    {
        return;
    }

    var text;
    var value;

    if (DWRUtil._isArray(data))
    {
        // Loop through the data that we do have
        for (var i = 0; i < data.length; i++)
        {
            if (useOptions)
            {
                if (valuerev != null)
                {
                    if (textprop != null)
                    {
                        text = data[i][textprop];
                        value = data[i][valuerev];
                    }
                    else
                    {
                        value = data[i][valuerev];
                        text = value;
                    }
                }
                else
                {
                    if (textprop != null)
                    {
                        text = data[i][textprop];
                        value = text;
                    }
                    else
                    {
                        text = "" + data[i];
                        value = text;
                    }
                }

                var opt = new Option(text, value);
                ele.options[ele.options.length] = opt;
            }
            else
            {
                li = document.createElement("li");
                li.innerHTML = "" + data[i];
                ele.appendChild(li);
            }
        }
    }
    else
    {
        for (var prop in data)
        {
            if (!useOptions)
            {
                //alert("DWRUtil.addOptions can only create select lists from objects.");
                return;
            }

            if (valuerev)
            {
                text = prop;
                value = data[prop];
            }
            else
            {
                text = data[prop];
                value = prop;
            }

            var opt = new Option(text, value);
            ele.options[ele.options.length] = opt;
        }
    }
};

/**
 * Remove all the options from a select list (specified by id)
 * @see http://www.getahead.ltd.uk/dwr/util-list.html
 * @param ele The id of the list element or the HTML element itself
 */
DWRUtil.removeAllOptions = function(ele)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("removeAllOptions() can't find an element with id: " + orig + ".");
        return;
    }

    var useOptions = DWRUtil._isHTMLElement(ele, "select");
    var useLi = DWRUtil._isHTMLElement(ele, ["ul", "ol"]);

    if (!useOptions && !useLi)
    {
        //alert("removeAllOptions() can only be used with select, ol and ul elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
        return;
    }

    if (useOptions)
    {
        // Empty the list
        ele.options.length = 0;
    }
    else
    {
        while (ele.childNodes.length > 0)
        {
            ele.removeChild(ele.firstChild);
        }
    }
};

////////////////////////////////////////////////////////////////////////////////
// The following functions are described in util-table.html

/**
 * Create rows inside a the table, tbody, thead or tfoot element (given by id).
 * The normal case would be to use tbody since that allows you to keep header
 * lines separate, but this function should work with and table element above
 * tr.
 * This function creates a row for each element in the <code>data</code> array
 * and for that row create one cell for each function in the
 * <code>cellFuncs</code> array by passing the element from the
 * <code>data</code> array to the given function.
 * The return from the function is used to populate the cell.
 * <p>The pseudo code looks something like this:
 * <pre>
 *   for each member of the data array
 *     for function in the cellFuncs array
 *       create cell from cellFunc(data[i])
 * </pre>
 * One slight modification to this is that any members of the cellFuncs array
 * that are strings instead of functions, the strings are used as cell contents
 * directly.
 * @see http://www.getahead.ltd.uk/dwr/util-table.html
 * @param ele The id of the tbody element
 * @param data Array containing one entry for each row in the updated table
 * @param cellFuncs An array of functions (one per column) for extracting cell
 *    data from the passed row data
 */
DWRUtil.addRows = function(ele, data, cellFuncs)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("addRows() can't find an element with id: " + orig + ".");
        return;
    }

    if (!DWRUtil._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"]))
    {
        //alert("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
        return;
    }

    // assure bug-free redraw in Gecko engine by
    // letting window show cleared table
    if (navigator.product && navigator.product == "Gecko")
    {
        setTimeout(function() { DWRUtil._addRowsInner(ele, data, cellFuncs); }, 0);
    }
    else
    {
        DWRUtil._addRowsInner(ele, data, cellFuncs);
    }
};

/**
 * Internal function to help rendering tables.
 * @see DWRUtil.addRows(ele, data, cellFuncs)
 * @private
 */
DWRUtil._addRowsInner = function(ele, data, cellFuncs)
{
    var frag = document.createDocumentFragment();

    if (DWRUtil._isArray(data))
    {
        // loop through data source
        for (var i = 0; i < data.length; i++)
        {
            DWRUtil._addRowInner(frag, data[i], cellFuncs);
        }
    }
    else if (typeof data == "object")
    {
        for (var row in data)
        {
            DWRUtil._addRowInner(frag, row, cellFuncs);
        }
    }

    ele.appendChild(frag);
};

/**
 * Iternal function to draw a single row of a table.
 * @private
 */
DWRUtil._addRowInner = function(frag, row, cellFuncs)
{
    var tr = document.createElement("tr");

    for (var j = 0; j < cellFuncs.length; j++)
    {
        var func = cellFuncs[j];
        var td;

        if (typeof func == "string")
        {
            td = document.createElement("td");
            var text = document.createTextNode(func);
            td.appendChild(text);
            tr.appendChild(td);
        }
        else
        {
            var reply = func(row);

            if (DWRUtil._isHTMLElement(reply, "td"))
            {
                td = reply;
            }
            else if (DWRUtil._isHTMLElement(reply))
            {
                td = document.createElement("td");
                td.appendChild(reply);
            }
            else
            {
                td = document.createElement("td");
                td.innerHTML = reply;
                //var text = document.createTextNode(reply);
                //td.appendChild(text);
            }

            tr.appendChild(td);
        }
    }

    frag.appendChild(tr);
};

/**
 * Remove all the children of a given node.
 * Most useful for dynamic tables where you clearChildNodes() on the tbody
 * element.
 * @see http://www.getahead.ltd.uk/dwr/util-table.html
 * @param ele The id of the element or the HTML element itself
 */
DWRUtil.removeAllRows = function(ele)
{
    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("removeAllRows() can't find an element with id: " + orig + ".");
        return;
    }

    if (!DWRUtil._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"]))
    {
        //alert("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
        return;
    }

    while (ele.childNodes.length > 0)
    {
        ele.removeChild(ele.firstChild);
    }
};

////////////////////////////////////////////////////////////////////////////////
// Private functions only below here

/**
 * Browser detection code.
 * This is eeevil, but the official way [if (window.someFunc) ...] does not
 * work when browsers differ in rendering ability rather than the use of someFunc()
 * For internal use only.
 * @private
 */
DWRUtil._agent = navigator.userAgent.toLowerCase();

/**
 * @private
 */
DWRUtil._isIE = ((DWRUtil._agent.indexOf("msie") != -1) && (DWRUtil._agent.indexOf("opera") == -1));

/**
 * Is the given node an HTML element (optionally of a given type)?
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The element to test
 * @param nodeName eg "input", "textarea" - optional extra check for node name
 *                 or an array of valid node names.
 * @private
 */
DWRUtil._isHTMLElement = function(ele, nodeName)
{
    if (ele == null || typeof ele != "object" || ele.nodeName == null)
    {
        return false;
    }

    if (nodeName != null)
    {
        var test = ele.nodeName.toLowerCase();

        if (typeof nodeName == "string")
        {
            return test == nodeName.toLowerCase();
        }

        if (DWRUtil._isArray(nodeName))
        {
            var match = false;
            for (var i = 0; i < nodeName.length && !match; i++)
            {
                if (test == nodeName[i].toLowerCase())
                {
                    match =  true;
                }
            }

            return match;
        }

        //alert("DWRUtil._isHTMLElement was passed test node name that is neither a string or array of strings");
    }
};

/**
 * Like typeOf except that more information for an object is returned other
 * than "object"
 * @private
 */
DWRUtil._detailedTypeOf = function(x)
{
    var reply = typeof x;

    if (reply == "object")
    {
        reply = Object.prototype.toString.apply(x);  // Returns "[object class]"
        reply = reply.substring(8, reply.length-1);  // Just get the class bit
    }

    return reply;
};

/**
 * Array detector.
 * This is an attempt to work around the lack of support for instanceof in
 * some browsers.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param data The object to test
 * @returns true iff <code>data</code> is an Array
 * @private
 */
DWRUtil._isArray = function(data)
{
    return (data && data.join) ? true : false;
};

/**
 * Date detector.
 * This is an attempt to work around the lack of support for instanceof in
 * some browsers.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param data The object to test
 * @returns true iff <code>data</code> is a Date
 * @private
 */
DWRUtil._isDate = function(data)
{
    return (data && data.toUTCString) ? true : false;
};

////////////////////////////////////////////////////////////////////////////////
// Deprecated functions only below here

/**
 * Is the given node an HTML element (optionally of a given type)?
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The element to test
 * @param nodeName eg input, textarea - optional extra check for node name
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.isHTMLElement)
{
DWRUtil.isHTMLElement = function(ele, nodeName)
{
    DWRUtil._deprecated("DWRUtil.isHTMLElement");

    if (nodeName == null)
    {
        // If I.E. worked properly we could use:
        //  return typeof ele == "object" && ele instanceof HTMLElement;
        return ele != null &&
               typeof ele == "object" &&
               ele.nodeName != null;
    }
    else
    {
        return ele != null &&
               typeof ele == "object" &&
               ele.nodeName != null &&
               ele.nodeName.toLowerCase() == nodeName.toLowerCase();
    }
};
}

/**
 * Like typeOf except that more information for an object is returned other
 * than "object"
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.detailedTypeOf)
{
DWRUtil.detailedTypeOf = function(x)
{
    DWRUtil._deprecated("DWRUtil.detailedTypeOf");

    var reply = typeof x;

    if (reply == "object")
    {
        reply = Object.prototype.toString.apply(x);  // Returns "[object class]"
        reply = reply.substring(8, reply.length-1);  // Just get the class bit
    }

    return reply;
};
}

/**
 * Array detector.
 * This is an attempt to work around the lack of support for instanceof in
 * some browsers.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param data The object to test
 * @returns true iff <code>data</code> is an Array
 * @deprecated Not sure if DWR is the right place for this or if we support old browsers
 */
if (!DWRUtil.isArray)
{
DWRUtil.isArray = function(data)
{
    DWRUtil._deprecated("DWRUtil.isArray", "(array.join != null)");
    return (data && data.join) ? true : false;
};
}

/**
 * Date detector.
 * This is an attempt to work around the lack of support for instanceof in
 * some browsers.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param data The object to test
 * @returns true iff <code>data</code> is a Date
 * @deprecated Not sure if DWR is the right place for this or if we support old browsers
 */
if (!DWRUtil.isDate)
{
DWRUtil.isDate = function(data)
{
    return (data && data.toUTCString) ? true : false;
};
}

/**
 * Is the given node an HTML input element?
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The element to test
 * @deprecated See the documentation for alternatives
 */
if (!DWRUtil.isHTMLInputElement)
{
DWRUtil.isHTMLInputElement = function(ele)
{
    DWRUtil._deprecated("DWRUtil.isHTMLInputElement");
    return DWRUtil.isHTMLElement(ele, "input");
};
}

/**
 * Is the given node an HTML textarea element?
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The element to test
 * @deprecated See the documentation for alternatives
 */
if (!DWRUtil.isHTMLTextAreaElement)
{
DWRUtil.isHTMLTextAreaElement = function(ele)
{
    DWRUtil._deprecated("DWRUtil.isHTMLTextAreaElement");
    return DWRUtil.isHTMLElement(ele, "textarea");
};
}

/**
 * Is the given node an HTML select element?
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The element to test
 * @deprecated See the documentation for alternatives
 */
if (!DWRUtil.isHTMLSelectElement)
{
DWRUtil.isHTMLSelectElement = function(ele)
{
    DWRUtil._deprecated("DWRUtil.isHTMLSelectElement");
    return DWRUtil.isHTMLElement(ele, "select");
};
}

/**
 * Like document.getElementById() that works in more browsers.
 * @param id The id of the element
 * @deprecated Use $()
 */
if (!DWRUtil.getElementById)
{
DWRUtil.getElementById = function(id)
{
    DWRUtil._deprecated("DWRUtil.getElementById", "$");

    if (document.getElementById)
    {
        return document.getElementById(id);
    }
    else if (document.all)
    {
        return document.all[id];
    }

    return null;
};
}

/**
 * Visually enable or diable an element.
 * @see http://www.getahead.ltd.uk/dwr/util-compat.html
 * @param ele The id of the element or the HTML element itself
 * @param state Boolean true/false to set if the element should be enabled
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.setEnabled)
{
DWRUtil.setEnabled = function(ele, state)
{
    DWRUtil._deprecated("DWRUtil.setEnabled");

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("setEnabled() can't find an element with id: " + orig + ".");
        return;
    }

    // If we want to get funky and disable divs and spans by changing the font
    // colour or something then we might want to check the element type before
    // we make assumptions, but in the mean time ...
    // if (DWRUtil.isHTMLElement(ele, "input")) { ... }

    ele.disabled = !state;
    ele.readonly = !state;
    if (DWRUtil._isIE)
    {
        if (state)
        {
            ele.style.backgroundColor = "White";
        }
        else
        {
            // This is WRONG but the hack will do for now.
            ele.style.backgroundColor = "Scrollbar";
        }
    }
};
}

/**
 * Set the CSS display style to 'block'
 * @param ele The id of the element or the HTML element itself
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.showById)
{
DWRUtil.showById = function(ele)
{
    DWRUtil._deprecated("DWRUtil.showById");

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("showById() can't find an element with id: " + orig + ".");
        return;
    }

    // Apparently this works better that display = 'block'; ???
    ele.style.display = '';
};
}

/**
 * Set the CSS display style to 'none'
 * @param ele The id of the element or the HTML element itself
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.hideById)
{
DWRUtil.hideById = function(ele)
{
    DWRUtil._deprecated("DWRUtil.hideById");

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("hideById() can't find an element with id: " + orig + ".");
        return;
    }

    ele.style.display = 'none';
};
}

/**
 * Toggle an elements visibility
 * @param ele The id of the element or the HTML element itself
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.toggleDisplay)
{
DWRUtil.toggleDisplay = function(ele)
{
    DWRUtil._deprecated("DWRUtil.toggleDisplay");

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("toggleDisplay() can't find an element with id: " + orig + ".");
        return;
    }

    if (ele.style.display == 'none')
    {
        // Apparently this works better that display = 'block'; ???
        ele.style.display = '';
    }
    else
    {
        ele.style.display = 'none';
    }
};
}

/**
 * Alter an rows in a table that have a class of zebra to have classes of either
 * oddrow or evenrow alternately.
 * This is probably not the best place for this method, but I dont want to have
 * to fight with multiple onload functions.
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.alternateRowColors)
{
DWRUtil.alternateRowColors = function()
{
    DWRUtil._deprecated("DWRUtil.alternateRowColors");

    var tables = document.getElementsByTagName("table");
    var rowCount = 0;

    for (var i = 0; i < tables.length; i++)
    {
        var table = tables.item(i);
        var rows = table.getElementsByTagName("tr");

        for (var j = 0; j < rows.length; j++)
        {
            var row = rows.item(j);
            if (row.className == "zebra")
            {
                if (rowCount % 2)
                {
                    row.className = 'oddrow';
                }
                else
                {
                    row.className = 'evenrow';
                }

                rowCount++;
            }
        }

        rowCount = 0;
    }
};
}

/**
 * Set the CSS class for an element
 * @param ele The id of the element or the HTML element itself
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.setCSSClass)
{
DWRUtil.setCSSClass = function(ele, cssclass)
{
    DWRUtil._deprecated("DWRUtil.setCSSClass");

    var orig = ele;
    ele = $(ele);
    if (ele == null)
    {
        //alert("setCSSClass() can't find an element with id: " + orig + ".");
        return;
    }

    ele.className = cssclass;
};
}

/**
 * Ensure a function is called when the page is loaded
 * @param load The function to call when the page has been loaded
 * @deprecated DWR isn't a generic Javascript library
 */
if (!DWRUtil.callOnLoad)
{
DWRUtil.callOnLoad = function(load)
{
    DWRUtil._deprecated("DWRUtil.callOnLoad", "window.addEventListener or window.onload");

    if (window.addEventListener)
    {
        window.addEventListener("load", load, false);
    }
    else if (window.attachEvent)
    {
        window.attachEvent("onload", load);
    }
    else
    {
        window.onload = load;
    }
};
}

/**
 * Remove all the options from a select list (specified by id) and replace with
 * elements in an array of objects.
 * @deprecated Use DWRUtil.removeAllOptions(ele); DWRUtil.addOptions(ele, data, valueprop, textprop);
 */
if (!DWRUtil.fillList)
{
DWRUtil.fillList = function(ele, data, valueprop, textprop)
{
    DWRUtil._deprecated("DWRUtil.fillList", "DWRUtil.addOptions");
    DWRUtil.removeAllOptions(ele);
    DWRUtil.addOptions(ele, data, valueprop, textprop);
};
}

/**
 * Add rows to a table
 * @deprecated Use DWRUtil.addRows()
 */
if (!DWRUtil.drawTable)
{
DWRUtil.drawTable = function(ele, data, cellFuncs)
{
    DWRUtil._deprecated("DWRUtil.drawTable", "DWRUtil.addRows");
    DWRUtil.addRows(ele, data, cellFuncs);
};
}

/**
 * Remove all the children of a given node.
 * Most useful for dynamic tables where you clearChildNodes() on the tbody
 * element.
 * @param id The id of the element
 * @deprecated Use DWRUtil.removeAllRows()
 */
if (!DWRUtil.clearChildNodes)
{
DWRUtil.clearChildNodes = function(id)
{
    DWRUtil._deprecated("DWRUtil.clearChildNodes", "DWRUtil.removeAllRows");

    var ele = DWRUtil.getElementById(id);
    if (ele == null)
    {
        //alert("clearChildNodes() can't find an element with id: " + id + ".");
        throw id;
    }

    while (ele.childNodes.length > 0)
    {
        ele.removeChild(ele.firstChild);
    }
};
}

/**
 * Do we alert on deprecation warnings
 * @private
 */
DWRUtil._showDeprecated = true;

/**
 * We can use this function to deprecate things.
 * @deprecated
 * @private
 */
DWRUtil._deprecated = function(fname, altfunc)
{
    if (DWRUtil._showDeprecated)
    {
        var warning;
        var alternative;

        if (fname == null)
        {
            warning = "You have used a deprecated function which could be removed in the future.";
            alternative = "";
        }
        else
        {
            warning = "Utility functions like '" + fname + "' are deprecated and could be removed in the future.";

            if (altfunc == null)
            {
                alternative = "\nSee the documentation for alternatives.";
            }
            else
            {
                alternative = "\nFor an alternative see: " + altfunc;
            }
        }

        var further = "\nImport deprecated.js to get rid of this warning.\nDo you wish to ignore further deprecation warnings on this page?";

        DWRUtil._showDeprecated = !confirm(warning + alternative + further);
    }
};
