String.prototype.trim = function()
{
    return this.match(/\s*([^\s]*)\s*/)[1];
}

/**
 * Gets the unescaped value of a named URL parameter. JQuery's $.getURLParam does not unescape the values
 * it returns.
 */
function urlParam(name)
{
    var param = $.getURLParam(name);
    return param ? decodeURIComponent(param) : null;
}

function DOMBuilder(root)
{
    this.curNode = root;
}

DOMBuilder.prototype.leaf = function(name)
{
    var e = document.createElement(name);
    this.curNode.appendChild(e);
    return e;
}

DOMBuilder.prototype.elem = function(name)
{
    this.curNode = this.leaf(name);
    return this.curNode;
}

DOMBuilder.prototype.end = function()
{
    if (this.curNode.parentNode)
        this.curNode = this.curNode.parentNode;
}

DOMBuilder.prototype.attr = function(name, value)
{
    this.curNode.setAttribute(name, value);

    // Nasty IE hacks. Some IE attributes have a corrosponding property which must be set to
    // the same value as the attribute. Most notably, the value assigned to the class attribute
    // must also be set to the className property.
    if (name == "class") this.prop("className", value);
}

DOMBuilder.prototype.prop = function(name, value)
{
    this.curNode[name] = value;
}

DOMBuilder.prototype.style = function(name, value)
{
    this.curNode.style[name] = value;
}

DOMBuilder.prototype.html = function(html)
{
    $(this.curNode).append(html);
}

DOMBuilder.prototype.text = function(text)
{
    $(this.curNode).append(document.createTextNode(text));
}
