// Constants.
var DAYS =
[
    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
];

var MONTHS =
[
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
];
                
var SUNDAY    = 0;
var MONDAY    = 1;
var TUESDAY   = 2;
var WEDNESDAY = 3;
var THURSDAY  = 4;
var FRIDAY    = 5;
var SATURDAY  = 6;

// Creates a new element with the specified name, attributes, and value. This
// abstraction of document.createElement() is necessary since Internet Explorer
// doesn't handle certain attributes being set via element.setAttribute()
// properly.
// 
// Parameters:
//     name:       The name of the element.
//     attributes: An array of attributes. Each element of the array should be a
//                 sub-array with two elements, the first the attribute's name
//                 and the second its value.
//     children:   If supplied, an array of child nodes and strings, which are
//                 converted into text nodes.
//
// Returns:
//     A new element.
function createElement(name, attributes, children)
{
    var element;

    if (attributes == null) attributes = [];
    if (children   == null) children   = [];
    
    // IE doesn't handle certain attributes like class or onChange being set with
    // element.setAttribute, so we'll create the element in a different way.
    if (navigator.userAgent.match(/MSIE [4-8]/i) && !navigator.userAgent.match(/Opera/i))
    {
        var elementString = name;
        
        for (var name in attributes)
            elementString += " " + name + '="' + escapeHtml(attributes[name]) + '"';

        element = document.createElement("<" + elementString + ">");
    }
    else
    {
        element = document.createElement(name);
        
        for (var attribute in attributes)
            element.setAttribute(attribute, attributes[attribute]);
    }
    
    setContent(element, children);
    
    return Element(element);
}

// Sets the child nodes of an element to a new set of nodes.
//
// Parameters:
//     element: The element to modify.
//     content: An array of HTML nodes and text strings, which are converted to
//              text nodes. For a single node, content does not need to be an
//              array.
function setContent(element, content)
{
    while (element.hasChildNodes())
        element.removeChild(element.firstChild);
        
    if (!(content instanceof Array))
        content = [content];

    for (var i = 0; i < content.length; ++i)
    {
        if (content[i].nodeName)
            element.appendChild(content[i]);
        else
            element.appendChild(document.createTextNode(content[i]));
    }
}

// Replaces the characters ", &, <, and > with their HTML entities &quot;,
// &amp;, &lt;, and &gt;.
//
// Parameters:
//     html: The string to escape.
//
// Returns:
//     The escaped string.
function escapeHtml(html)
{
    return html.toString()
        .replace('"', "&quot;")
        .replace('&', "&amp;")
        .replace('<', "&lt;")
        .replace('>', "&gt;");
}
      
// Joins any number of associative arrays into a single array and returns the
// composite array.
function join(/* array1, array2, ..., arrayN */)
{
    var result = {};
    
    for (var i = 0; i < arguments.length; ++i)
    {
        if (arguments[i] instanceof Array)
        {
            for (var value in arguments[i])
                result[arguments[i][value]] = arguments[i][value];
        }
        else
        {
            for (var name in arguments[i])
                result[name] = arguments[i][name];
        }
    }
        
    return result;
}

