/**
 * This script builds a single variable (DOM) that provides functions for
 * creating dom elements.
 *
 * @author Philip Graham
 */
var dom = function () {
    /*=======================================================================*
     * Private Methods
     *=======================================================================*/

    /*
     * This function takes an object and uses it to build a string that can be
     * used to set a DOM elements css text.
     */
    var buildStyleString = function (styleObj) {
        var styleString = '';
        for (var attr in styleObj) {
            var prop = attr;
            if (attr != attr.toLowerCase()) {
                // This is a camelcased property so we need to convert it to
                // a '-' separated property
                for (var i = 0; i < attr.length; i++) {
                    var nextChar = attr.substring(i, i + 1);
                    if (nextChar != nextChar.toLowerCase()) {
                        // This is the camel-case character
                        attr = attr.substring(0, i) + '-' +
                            nextChar.toLowerCase() +
                            attr.substring(i + 1, attr.length);
                        break;
                    }
                }
            }
            styleString = styleString + attr + ':' + styleObj[prop] + ';';
        }
        return styleString;
    };

    /*=======================================================================*
     * Public Interface
     *=======================================================================*/
    return {
        /**
         * This function creates a new element of type tag.  Optional attrs
         * object and children array can be provided to initialize attributes
         * and attach children respectively.
         */
        create: function (tag, attrs, children) {
            attrs = attrs || {};
            children = children || [];

            // Take the element
            var elm = document.createElement(tag);

            // Handle attempts to set the style attribute diffenrent since
            // behaviour is browser specific
            if (typeof(attrs.style) == 'object') {
                elm.style.cssText = buildStyleString(attrs.style);

                // Unset the style attribute so that it doesn't get set below
                attrs.style = null;
            }

            // Set the given attributes
            for (var attr in attrs) {
                if(attr == 'className') {
                    elm.className = attrs[attr];
                } else if(attrs[attr] !== null) {
                    elm.setAttribute(attr, attrs[attr].toString());
                }
            }

            // Append children, creating text nodes for children
            for (var i = 0, l = children.length; i < l; i++) {
                if(typeof(children[i]) == 'string' ||
                    typeof(children[i]) == 'number') {
                    children[i] = document.createTextNode(children[i]);
                }
                elm.appendChild(children[i]);
            }

            return elm;
        },
        /**
         * This method takes the given form and returns a postable string of
         * its elements and their values.
         */
        createPostString: function (form) {
            var params = {};
            for(var i = 0; i < form.elements.length; i++) {
                var element = form.elements[i];
                if(element.type == 'button' || element.type == 'submit') {
                    continue;
                }
                // Encode any values that contain special characters
                var value = element.value;
                var elementIsTextArea =
                    element.nodeName.toLowerCase() == 'textarea';
                var elementIsMultipleSelect =
                    element.nodeName.toLowerCase() == 'select' &&
                    element.multiple;

                var valueHasPlus = value.indexOf('+') >= 0;
                if (elementIsTextArea || valueHasPlus) {
                    value = encodeURIComponent(value);
                }

                var elementNameEnd = element.name.substring(
                    element.name.length - 2, element.name.length);

                // Add the value of the elements to the post string.  Handle
                // special cases first

                // Multiple select boxes
                if (elementIsMultipleSelect) {
                    var selectedOpts = [];
                    for (var j = 0; j < element.options.length; j++) {
                        if (element.options[j].selected) {
                            selectedOpts[selectedOpts.length] =
                                element.options[j].value;
                        }
                    }
                    if (selectedOpts.length > 0) {
                        params[element.name] = selectedOpts;
                    }
                
                // File uploads
                } else if (element.type == 'file') {
                    continue;
                    /*
                    if(element.files) {
                        if(element.files.length > 0) {
                            var file = element.files.item(0);
                            if(file.getAsBinary) {
                                params[element.name] =
                                    encode64(file.getAsBinary());
                            }
                        }
                    }
                    */

                // Radio buttons
                } else if (element.type == 'radio') {
                    var elementName = element.name;
                    if (elementNameEnd == '[]') {
                        elementName = element.name.substring(
                            0, element.name.length - 2
                        );
                    }
                    if (element.checked) {
                        params[elementName] = value;
                    }

                // Check boxes
                } else if (element.type == 'checkbox') {
                    if (element.checked) {
                        if (!params[element.name]) {
                            params[element.name] = [];
                        }
                        params[element.name][params[element.name].length] =
                            value;
                    }

                // Array inputs
                } else if (elementNameEnd == '[]') {
                    if(!params[element.name]) {
                        params[element.name] = [];
                    }
                    params[element.name][params[element.name].length] = value;
                } else {
                    params[element.name] = value;
                }
            }
            return params;
        }
    };
}();
