// $Id: dom.js 35 2006-09-18 00:03:19Z unicinfo $
// Copyright (c) 2004 Kurt M. Brown.
// This file is subject to the terms and conditions of the GNU General Public
// License. See the file COPYING for more details.

function createDoc(str)
{
    return new DOMParser().parseFromString(str, 'text/xml');
}

function quoteString(str)
{
    var qs = '';
    if (str) {
        var s = new String(str);
        for (var i = 0; i < s.length; ++i) {
            if (s.charAt(i) == '<')
                qs += "&lt;";
            else if (s.charAt(i) == '>')
                qs += "&gt;";
            else if (s.charAt(i) == '&')
                qs += "&amp;";
            else if (s.charAt(i) == '"')
                qs += "&quot;";
            else if (s.charAt(i) == "'")
                qs += "&apos;";
            else
                qs += s.charAt(i);
        }
    }
    return qs;
}

Document.prototype.__defineGetter__(
    'toString',
    function() {
        return new XMLSerializer().serializeToString(xDoc);
    }
);
Document.prototype.__defineGetter__(
    'xml',
    function() {
        return (new XMLSerializer()).serializeToString(this);
    }
);

Node.prototype.__defineGetter__(
    'xml',
    function () {
        return (new XMLSerializer()).serializeToString(this);
    }
);

Document.prototype.selectNodes = function(xpath, contextNode)
{
    const result = this.evaluate(
        xpath,
        (contextNode == undefined ? this.documentElement : contextNode),
        this.createNSResolver(this.documentElement),
        XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
        null
    );
    var nodeList = new Array(result.snapshotLength);
    nodeList.expr = xpath;
    for (var i = 0; i < nodeList.length; ++i)
        nodeList[i] = result.snapshotItem(i);

    return nodeList;
}
Document.prototype.selectSingleNode = function(xpath, contextNode)
{
    const nodeList = this.selectNodes(xpath + '[1]', contextNode);
    return (nodeList.length > 0) ? nodeList[0] : null;
}

Element.prototype.removeAllChildren = function()
{
    while (this.hasChildNodes())
        this.removeChild(this.firstChild);

}
Element.prototype.selectNodes = function(xpath)
{
    return this.ownerDocument.selectNodes(xpath, this);
}
Element.prototype.selectSingleNode = function(xpath)
{
    return this.ownerDocument.selectSingleNode(xpath, this);
}
Element.prototype.setIntOrNothing = function(name, value)
{
    const val = parseInt(value, 10);
    if (!isNaN(val))
        this.setAttribute(name, val);
};
Element.prototype.setFloatOrNothing = function(name, value)
{
    const val = parseFloat(value);
    if (!isNaN(val))
        this.setAttribute(name, val);
};
Element.prototype.setBoolean = function(name, value)
{
    // needed to ensure a boolean is saved when the value is not a
    // boolean type (e.g., null, 0, 1, etc.).
    this.setAttribute(name, value ? 'true' : 'false');
}
Element.prototype.getAttributeOrNull = function(name)
{
    // getAttribute() returns null when the attribute does not exist.
    // Also return null when the attribute exists but is empty.
    const value = this.getAttribute(name);
    return value === null ? null : (value === '' ? null : value);
}
Element.prototype.getBoolean = function(name)
{
    return this.getAttribute(name) == 'true';
}
Element.prototype.getBooleanOrNull = function(name)
{
    // see getAttributeOrNull() for more info
    const value = this.getAttribute(name);
    return value === null ? null : (value === '' ? null : (value == 'true'));
}
Element.prototype.getNumber = function(name)
{
    // Number(x) == 0, where x is one of {null, undefined, '', 'random string'}
    return new Number(this.getAttribute(name));
}
Element.prototype.getNumberOrNull = function(name)
{
    const value = parseFloat(this.getAttribute(name));
    return isNaN(value) ? null : new Number(value);
}
