if (typeof _H !== 'object') var _H = {};

/* 
    Author: Fabrizio Calderan, http://www.fabriziocalderan.it/
    Version 1.0 release 2008-08-01.	
*/

_H.DOM = function() {
  
    /* Private properties */
        
    var _separator          =  "~";
    var _defaultNode        =  document.body;
        
        
    /* some useful shortcuts. Add your own shortcuts here. */
    var _shortProperties    =  {
            "class"     : "className",
            "for"       : "htmlFor",
            "longdesc"  : "longDesc",
            "text"      : "innerHTML",
            "url"       : "href"
    };
       
       
    /* 
        Entities can't be written with 'createTextNode' method, so we need to
        convert all entities into unicode sequences. Add your own entities here.
     */
    var _entityUnicode      = {
        "&quot;"    : "\u0022", 
        "&agrave;"  : "\u00e0", 
        "&ccedil;"  : "\u00e7", 
        "&egrave;"  : "\u00e8",
        "&eacute;"  : "\u00e9", 
        "&igrave;"  : "\u00ec", 
        "&ograve;"  : "\u00f2", 
        "&ugrave;"  : "\u00f9",
        "&laquo;"   : "\u00ab", 
        "&raquo;"   : "\u00bb",
        "&copy;"    : "\u00a9"
    };
        
        
    /* For memoization of nodes */
    var _cache                  = { };
        
    var _getElements    = function(e) { 
        return e.split(_separator)[0];       
    };
        
        
    var _createEntityReference  = function(text) {
        return text.replace(/(&[^;]+?;)/g, function(entity) {
            return _entityUnicode[entity] || "<unknown entity>";
        });
    };
        
        
        
    /* Public/Privileged methods */
        
    return {
            
        setSeparator    : function(s) {
            if (/^[^a-z]{1}$/i.test(s)) {
                _separator = s;
            }
        },
            
            
        remove          : function(node, complete) {
            var node = _H.$(node);
            if (node) {
                if (!!complete) {   
                    node.parentNode.removeChild(node); 
                };
                while (node.childNodes[0]) node.removeChild(node.childNodes[0]);
                return true;
            };
            return false;
        },
            
            
        create          : function(obj) {
			  
            /* Create a DOM Fragment */
            this.df = document.createDocumentFragment();
                
            /* Return a recursive function */
            return (function(obj, node, self) {
                    
                for (var p in obj) {
                        
                    if (obj.hasOwnProperty(p)) {
                        var el = _getElements(p);
                        
                        if (typeof obj[p] === 'object') {
                            if (!_cache[el]) { 
                                _cache[el] = document.createElement(el); 
                            };
                            var elementNode = _cache[el].cloneNode(false);
                            arguments.callee(obj[p], elementNode);
                            node.appendChild(elementNode); 
                        }
                        else {
                            var attribute = (_shortProperties[el])? _shortProperties[el] : el;
                            switch(attribute) {
                                    
                                case    "innerHTML" : 
                                    var textNode = document.createTextNode(_createEntityReference(obj[p]));
                                    node.appendChild(textNode); 
                                    break;
                                        
                                case    "style"     : 
                                    _H.setStyle(node, obj[p]);
                                    break;
                                        
                                        
                                default             : node[attribute] = obj[p];
                                
                            }
                        }
                    }
                    
                }; /* end [for..in] */
                    
                if (self) return self; /* end 'for' loop at first recursion */
                        
            })(obj, this.df, this);
                
        },
            
            
        append          : function(type, node) {
                
            _defaultNode = (node)
                ? _H.$(node)
                : _H.$(_defaultNode);
                
            if (_defaultNode) {
                switch(type.toLowerCase()) {
                
                    case "before"           : 
                            var pNode = _defaultNode.parentNode;
                            return pNode.insertBefore(this.df, _defaultNode);
                            break;
                    case "after"            : 
                            var pNode = _defaultNode.parentNode;
                            return pNode.insertBefore(this.df, _defaultNode.nextSibling);
                            break;
                            
                    case "into"             :
                    case "inside"           :
                            return _defaultNode.appendChild(this.df);
                            break;
                            
                    default : throw "Unknown 'type' argument in 'append' method."; 
                }                    
            };
                
            return false;
        }       
    }
};

