function HtmlParser(){

    var object;

    function parseAttributes(xmlObject,domNode){
        if(xmlObject.attributes === null){
            return;
        }
        var attrName;
        var attrValue;
        var counter;
        var upFunc = function(){ System.windowmanager.updateView(domNode); };
        var reqFunc = function(self){ makeRequest(self); };
        var copyFunc = function(self){ domNode.value = self.value; };
        var anonFunc = function(){};
        for(var x = 0; x < xmlObject.attributes.length; x++){
            attrName = xmlObject.attributes[x].name;
            attrValue = xmlObject.attributes[x].value;
            switch(attrName){
                case "overrule":
                    if(attrValue === "true"){
                        domNode.href = "javascript:return false;";
                    }
                    break;
                case "cache":
                    if(attrValue === "true"){
                        domNode.cached = true;
                    }
                    break;
                case "return":
                    var rValue = attrValue;
                    domNode.returnValue = rValue;
                    break;
                case "extsrc":
                    object.addSubscriber("onpostprocess",upFunc);
                    break;
                case "target":
                    var targetType = attrValue;
                    object.addSubscriber("onpostprocess",function(){
                        if(domNode.url !== undefined){
                            domNode.location = targetType;
                        }else{
                            domNode.setAttribute("target",targetType);
                        }
                    });
                    break;
                case "url":
                    domNode.url = attrValue;
                    domNode.addSubscriber("onclick",reqFunc);
                    domNode.addSubscriber("onenter",reqFunc);
                    break;
                case "grabfocus":
                    if(attrValue === "true"){
                        System.windowmanager.setFocusedObject(domNode);
                        object.addSubscriber("onpostprocess",System.windowmanager.refocus);
                    }
                    break;
                case "returnid":
                    if(attrValue !== ""){
                        domNode.returnId = attrValue;
                    }
                    break;
                case "replace":
                    if(attrValue !== ""){
                        domNode.replace = attrValue;
                    }
                    break;
                case "async":
                    if(xmlObject.nodeName === "form" && attrValue === "true"){
                        domNode.allowAsyncRequests = true;
                    }
                    break;
                case "update":
                    var updateFunc = attrValue;
                    domNode.addSubscriber("update",createFunctionFromString(updateFunc));
                    break;
                case "onclick":
                    var onClickAction = attrValue;
                    var func = new Function("self",onClickAction);
                    object.addSubscriber("onpostprocess",function(){
                        domNode.addSubscriber("onclick",func,domNode.returnValue);
                    });
                    break;
                case "onmouseover":
                    var onmouseoverAction = attrValue;
                    var mouseOverFunc = new Function("self",onmouseoverAction);
                    object.addSubscriber("onpostprocess",function(){
                        domNode.addSubscriber("onmouseover",mouseOverFunc,domNode.returnValue);
                    });
                    break;
                case "onchange":
                    var onChangeAction = attrValue;
                    var changeFunc = new Function("self",onChangeAction);
                    object.addSubscriber("onpostprocess",function(){
                        domNode.addSubscriber("onchange",changeFunc,domNode.returnValue);
                    });
                    break;
                case "updateonclick":
                    var onClickIds = attrValue.split(" ");
                    for(counter = 0; counter < onClickIds.length; counter++){
                        updateOnClick(onClickIds[counter],domNode);
                    }
                    break;
                case "updateonchange":
                    var onChangeIds = attrValue.split(" ");
                    for(counter = 0; counter < onChangeIds.length; counter++){
                        updateOnChange(onChangeIds[counter],domNode);
                    }
                    break;
                case "getvalueonchange":
                    var valueOnChangeId = attrValue;
                    anonFunc = function(self){
                        var node = document.getElementById(valueOnChangeId);
                        if(node !== null){
                            node.addSubscriber("onchange",copyFunc);
                        }
                    };
                    object.addSubscriber("onpostprocess",anonFunc);
                    break;
                case "cloneonchange":
                    var cloneonchangeid = attrValue;
                    object.addSubscriber("onpostprocess",function(){
                        var node = document.getElementById(cloneonchangeid);
                        if(node !== null){
                            System.publish(node);
                            node.addSubscriber("onchange",function(self){
                                var className = domNode.className;
                                var clonedNode = self.cloneNode(true);
                                clonedNode.selectedIndex = self.selectedIndex;
                                domNode.parentNode.replaceChild(clonedNode,domNode);
                                clonedNode.className = className;
                            });
                        }
                    });
                    break;
                case "style":
                    if(System.browser.isIE()){
                        domNode.style.cssText = attrValue;
                    }else{
                        domNode.setAttribute(attrName,attrValue);
                    }
                    break;
                case "class":
                    domNode.className = attrValue;
                    break;
                default:
                    domNode.setAttribute(attrName,attrValue);
                    break;
            }
        }
    }

    function createFunctionFromString(string){
        return new Function("self",string);
    }

    function updateOnChange(sourceId,destNode){
        object.addSubscriber("onpostprocess",function(){
            var node = document.getElementById(sourceId);
            if(node !== null){
                node.addSubscriber("onchange",function(self){
                    destNode.update();
                    //System.processFormToUrl(self.form,domNode.id,domNode.returnId,domNode.replace);
                });
            }
        });
    }

    function updateOnClick(sourceId,destNode){
        object.addSubscriber("onpostprocess",function(){
            var node = document.getElementById(sourceId);
            if(node !== null){
                node.addSubscriber("onclick",function(self){
                    destNode.update();
                    //System.windowmanager.updateView(destNode);
                });
            }
        });
    }

    function makeRequest(domNode){
        try{
            if(domNode.location === "_BLANK"){
                window.open(domNode.url);
                return;
            }

            if (domNode.location === "_REQUEST"){
                var node = document.getElementById(domNode.returnId);
                if(node != null && node.cached){
                    var xmlResponse = System.getCached(domNode.url);
                    if(xmlResponse !== null){
                        System.xmlparser.parse(xmlResponse);
                    }else{
                        var request = System.ajaxRequest(domNode.url,null,domNode.returnId);
                        request.addCallback(4, function(xmlDocument){ System.addCache(domNode.url,xmlDocument);});
                        request.send();
                    }
                    return;
                }
                System.ajaxRequest(domNode.url,null,domNode.returnId).send();
                return;
            }

            window.location = domNode.url;
        }catch(e){
            alert(e.toString());
        }
    }

    function processNode(xmlNode, domParent){
        var domNode;

        var name = xmlNode.nodeName;
        var value = xmlNode.nodeValue;
        var text = xmlNode.nodeValue;
        var className;
        switch(name){
            case "#comment":
                return null;
                break;
            case "#text":
                value = value.replace(/(\t|\r|\r\n|\n)/g," ");
                var firstChar = value.charAt(0);
                value = value.trim();
                if(value.charAt(0) != firstChar){
                    value = " "+value;
                }
                if(value == ""){
                    return null;
                }
                domNode = document.createTextNode(value);
                break;
            case "img":
                domNode = new Image();
                setClassName(xmlNode,domNode);
                System.publish(domNode);
                break;
            default:
                domNode = document.createElement(name);
                setClassName(xmlNode,domNode);
                System.publish(domNode);
                break;
        }
        
        parseAttributes(xmlNode,domNode);

        if(xmlNode.childNodes !== null){
            for(var x = 0; x < xmlNode.childNodes.length; x++){
                processNode(xmlNode.childNodes[x],domNode);
            }
        }
        
        if(domParent !== undefined && escape(value) !== "%0D%0A%20%20%20%20"){
            domParent.appendChild(domNode);
        }
        
        return domNode;
    }

    function setClassName(xmlNode,domNode){
        var className = xmlNode.getAttribute("class");
        if(className !== null){
            domNode.className = className;
        }
    }

    var htmlparser = {

        parse : function(xmlDocument, xmlObject){
            object = xmlObject;
            var parent = processNode(xmlDocument);
            return parent;
        }

    };

    System.htmlparser = htmlparser;
}
