
function DomInnerHtml() { }

DomInnerHtml.prototype.init = function() {
    this.position = [0];
    this.depth = 0;
    this.htmlTree = this.createElement('div');
};

// copied from a function which was I think originally written by Simon Willison (http://simon.incutio.com) - I could be wrong though...
DomInnerHtml.prototype.createElement = function(element) {
    if (document.createElementNS) {
        return document.createElementNS('http://www.w3.org/1999/xhtml', element);
    }
    if (document.createElement) {
        return document.createElement(element);
    }
    return false;
};

DomInnerHtml.prototype.clean = function(obj) {
    while (obj.hasChildNodes()) {
        obj.removeChild(obj.firstChild);
    }
};

DomInnerHtml.prototype.walk = function(node) {
    ++this.depth;
    if (this.position[this.depth] == undefined) {
        this.position[this.depth] = 0;
    }

    if (node.nodeType == 1) {
        var el = this.createElement(node.nodeName);
        for (var i = 0; i < node.attributes.length; ++i) {
            el.setAttribute(node.attributes[i].name, node.attributes[i].value);
        }
    } else if (node.nodeType == 3) {
        var el = document.createTextNode(node.nodeValue);
    }

    this.buildDomTree(el);

    if (node.hasChildNodes()) {
        for (var i = 0; i < node.childNodes.length; ++i) {
            this.walk(node.childNodes[i]);
        }
    } 

    ++this.position[this.depth];
    this.position.splice(this.depth + 1, 1);
    --this.depth;
};

DomInnerHtml.prototype.buildDomTree = function(el) {
    var node = this.htmlTree;
    for (var i = 1; i < this.position.length - 1; ++i) {
        node = node.firstChild;
        for (var j = 0; j < this.position[i]; ++j) {
            node = node.nextSibling;
        }      
    }
    node.appendChild(el);
};

DomInnerHtml.prototype.write = function(str, replace, target) {
    this.init();

    if (typeof target == 'string') {
        var target = document.getElementById(target);
    } else if (target == undefined) {
        var target = document.getElementsByTagName('body')[0];
    }

    if (!target) {
        return false;
    }

    if (window.DOMParser) {
        try {
            var dom = (new DOMParser()).parseFromString('<div>' + str + '</div>', 'text/xml');
            if (dom.firstChild.nodeName == 'parsererror') {
                return false;
            }
        } catch(e) {
            return false;
        }

        this.walk(dom.firstChild);

        if (replace) {
            this.clean(target);
        }
        
        var i = this.htmlTree.firstChild.childNodes.length;
        var tmp = [];
        while (i--) {
            tmp.push(this.htmlTree.firstChild.childNodes[i]);
        }

        var i = tmp.length;
        while (i--) {
            target.appendChild(tmp[i]);
        }

    } else {
        if (replace) {
            target.innerHTML = str;
        } else {
            target.innerHTML += str;
        }
    }
    return true;
};
