
/*
 * weinre is available under *either* the terms of the modified BSD license *or* the
 * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
 * 
 * Copyright (c) 2010, 2011 IBM Corporation
 */

//-----------------------------------------------------------------------------
// creates functions of the form H1, H2, etc, as static methods that create a new element
// of the specified name.  The function can take a variable number of arguments,
// which are either child elements, strings, attributes, or properties of the element.
//
// - arguments which are nodes become children
// - arguments which are strings become text node children
// - arguments which are objects have the object's properties added as:
//    - attributes if the property name does not begin with "$"
//    - properties if the property name begins with "$" 
//      (the resulting property name doesn't include "$")
//-----------------------------------------------------------------------------

requireClass ../common/Ex

//-----------------------------------------------------------------------------
class DOMTemplates

//-----------------------------------------------------------------------------
function getElementFunction(elementName)
    return function() {
        var element = document.createElement(elementName)
        
        var args = [].slice.call(arguments)
        args.forEach(function(argument) {
            if      (argument.nodeType)           addToElement_Node(   element, argument )
            else if (typeof argument == "string") addToElement_String( element, argument )
            else if (typeof argument == "object") addToElement_Object( element, argument )
            else throw new Ex(arguments, "invalid value passed to  DOMTemplates." + elementName + "(): " + argument)
        })
        
        return element
    }

//-----------------------------------------------------------------------------
function addToElement_String(element, aString)
    addToElement_Node(element, document.createTextNode(aString))

//-----------------------------------------------------------------------------
function addToElement_Node(element, anElement)
    element.appendChild(anElement)

//-----------------------------------------------------------------------------
function addToElement_Object(element, anObject)
    for (var key in anObject) {
        if (!anObject.hasOwnProperty(key)) continue
        
        var val = anObject[key]
        
        if (key.substr(0,1) == "$") {
            var actualKey = key.substr(1)
            element[actualKey] = val
        }
        else {
            element.setAttribute(key, val)
        }
    }

//-----------------------------------------------------------------------------
init 
    var elementNames = "H1 H2 H3 H4 H5 H6 UL OL DL LI DT DD SPAN DIV A B I TT P HR BR PRE IMG CANVAS TABLE TR TD FORM INPUT BUTTON SELECT OPTGROUP OPTION TEXTAREA"
    elementNames = elementNames.split(" ")
    
    elementNames.forEach(function(elementName) {
        DOMTemplates[elementName] = getElementFunction(elementName)
    })
