var elementify = function(o) {
    var known = {};
    var unknown = {};
    var el;
    
    if ((typeof o.length).toLowerCase() === 'number' && (typeof o.splice).toLowerCase() === 'function') {
        var elements = [];
        for (var x=0; x < o.length; x++) {
            elements.push(elementify(o[x]));
        };
        return elements;
    }
    
    function addEvents(obj) {
        for (x in obj) {
            if( el.attachEvent ) {
                el["e"+x+obj[x].fn] = obj[x].fn;
                el[x+obj[x].fn] = function(){el["e"+x+obj[x].fn]( window.event );};
                el.attachEvent( "on"+x, el[x+obj[x].fn] );

            } else {
                el.addEventListener( x, obj[x].fn, true );
            }
        }
    };
    var merge = function(o, f) {
        try {
            for (var x in f) {
                o[x] = f[x];
            }
        } catch (e) {
            alert('Error: could not merge object on :: ' + x)
        }
        
        return o;
    }
    
    if (!o.tagName) {
        alert('Error: Tried to create element without specifying a tagName' + o);
        return null;
    } else {
        el = document.createElement(o.tagName);
    }
    
    
    for (var x in o) {
        if (x.search(/style|content|events|append/gi) > -1) {
            known[x] = o[x];
        } else if (x.search(/tagname/gi) > -1) {
            //do nothing
        } else {
            unknown[x] = o[x];
        }
    }
    
    merge(el, unknown);
    
    try {
        for (var x in known) {
            switch (x) {
                case 'style' : {
                    merge(el[x], known[x]);
                } break;
                case 'content' : {
                    el.appendChild(document.createTextNode(known[x]));
                } break;
                case 'events' : {
                    addEvents(known[x]);
                } break;
                case 'append' : {
                    if ((typeof known[x].length).toLowerCase() === 'number' && (typeof known[x].splice).toLowerCase() === 'function') {
                        for (var y=0; y < known[x].length; y++) {
                            el.appendChild(known[x][y]);
                        };
                    } else {
                        el.appendChild(known[x]);
                    }
                } break;
            }
        }
    } catch(e) {
        alert('Error: could not parse and execute known functions')
    }
    return el;
}

