// DOM element creator for jQuery and Prototype by Michael Geary
// http://mg.to/topics/programming/javascript/jquery
// Inspired by MochiKit.DOM by Bob Ippolito
// Free beer and free speech. Enjoy!

//Modified by Thomas Wild 17/04/2009 to enable setting of style as a paremeter
//In the creation functions eg
//var dv = $.DIV({"id":'testDiv',"style":'background-color:red; width:10em; float:right;font-size:2px; font-weight:bold'});
//It will loop through the style rules correcting for dashes and the float property
//In addition updated the try catch error message to include the actual exception
//that occured.

$.defineTag = function( tag ) {
    $[tag.toUpperCase()] = function() {
        return $._createNode( tag, arguments );
    }
};

(function() {
    var tags = [
    'a', 'br', 'button', 'canvas', 'div', 'fieldset', 'form',
    'h1', 'h2', 'h3', 'hr', 'img', 'input', 'label', 'legend',
    'li', 'ol', 'optgroup', 'option', 'p', 'pre', 'select',
    'span', 'strong', 'table', 'tbody', 'td', 'textarea',
    'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'Iframe' ];
    for( var i = tags.length - 1;  i >= 0;  i-- ) {
        $.defineTag( tags[i] );
    }
})();

$.NBSP = '\u00a0';

$._createNode = function( tag, args ) {
    var fix = {
        'class':'className',
        'Class':'className',
        'Style':'style'
    };
    var cssFix = {
        'float':'cssFloat'
    }
    var e;
    
    var jsTrim     = function phpJStrim (str) {
        //Strips whitespace from the beginning and end of a string
        //http://phpjs.org/functions/trim
        //Custom character list parameter removed by T.Wild 17/04/2009
        var whitespace, l = 0, i = 0;str += '';
        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
        l = str.length;
        for (i = 0; i < l; i++) {
            if (whitespace.indexOf(str.charAt(i)) === -1) {
                str = str.substring(i);break;
            }
        }
        l = str.length;
        for (i = l - 1; i >= 0; i--) {
            if (whitespace.indexOf(str.charAt(i)) === -1) {
                str = str.substring(0, i + 1);
                break;
            }
        }
        return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
    }
    var fixCssName = function fixCssNameDash(name){
        name = name.toString();
        name = name.toLowerCase();
        var l = name.length;
        var Nname = '';
        var NextCharacter = false;
        for(var x=0; x<l;x++){
            if(name.charAt(x) == '-'){
                NextCharacter = true;
            }else if (NextCharacter){
                Nname+=name.charAt(x).toUpperCase();
                NextCharacter = false;
            }else{
                Nname+=name.charAt(x);
            }
        }
        return Nname;
    }
    try {
        var attrs = args[0] || {};
        var styles,l,vals,name,value;
        e = document.createElement( tag );
        for( var attr in attrs ) {
            var a = fix[attr] || attr;
            if (a == 'style'){
                styles = attrs[attr].toString().split(";");
                l = styles.length;
                vals = [],name='',value='';
                for(var indx=0; indx<l; indx++){
                    vals  = styles[indx].toString().split(":");
                    if(vals != ''){
                        name  = jsTrim(vals[0]);
                        name  = cssFix[vals[0]] || fixCssName(vals[0]);
                        value = jsTrim(vals[1]);
                        try{
                            e.style[name] = value;
                        }catch( exAlpha ){
                            alert('Error applying styles to <' + tag + '> element\n' +
                                'The exception provided was:\n' + exAlpha + '\n' +
                                'The style and value that failed to apply was\n' +
                                '{' + name + ':\n' + value + '}\n' +
                                'The raw value provied in the array was:\n{' + attrs[attr] + '}');
                        }
                    }
                }
            }else{
                e[a] = attrs[attr];
            }
        }
        for( var i = 1;  i < args.length;  i++ ) {
            var arg = args[i];
            if( arg == null ) continue;
            if( arg.constructor != Array ) append( arg );
            else for( var j = 0;  j < arg.length;  j++ )
                append( arg[j] );
        }
    }
    catch( ex ) {
        try{
            alert('Cannot create <' + tag + '> element:\n' +
                'The error reported was:\n' + ex + '\n' +
                'These were the arguments passed to the constructor function:\n' +
                args.toSource() + '\n -------------------------- \n' + args);
        }catch( ex2){
            alert('Cannot create <' + tag + '> element:\n' +
                'exception was:\n' + ex + '\n\n' +
                'There was also an error when generating the detailed error message,\n' +
                'This error was:\n' + ex2);
        }
        
        e = null;
    }

    function append( arg ) {
        if( arg == null ) return;
        //var c = arg.constructor;
        switch( typeof arg ) {
            case 'number': arg = '' + arg;  // fall through
            case 'string': arg = document.createTextNode( arg );
        }
        e.appendChild( arg );
    }

    return e;
};
