
/*
 * 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, 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

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(" ")

//-----------------------------------------------------------------------------
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 
    ElementNames.forEach(function(elementName) {
        DOMTemplates[elementName] = getElementFunction(elementName)
    })
