function initWebform(webformID, fields)
{
    // register a handler for the form
    var formname = 'webform_'+webformID;
    
    // Add error checkers to specific elements.
    for (id in fields)
    {
        // locate field.
        var field = fields[id];
                
        // locate element
        var element = document.getElementById(id);
        
        // Add a error checker.
        webform_add_error_checker(element, field);
    }
    
    document.forms[formname].onsubmit = function()
    {
        // array of encountered errors
        var errors = [];

        // Loop trough the fields and attach input checks.
        for (id in fields)
        {
            // leap out if we already discovered too many errors
            if (errors.length >= 4) break;

            // Locate field.
            var field = fields[id];
            var value = false;
            
            // Value of dropdown.
            if (field.type == "dropdown")
            {
                var selectIndex = this[id].selectedIndex;
                value = this[id].options[selectIndex].text;
            }
            else if (field.type == "password_repeat")
            {
                // matching field
                if (this[id].value != this[id+'_repeat'].value)
                {
                    // an error was detected
                    errors.push(get_webform_error_message('passwords_do_not_match', {field: field.label}));
                    
                    // continue to the next field.
                    continue;
                }
                
                value = this[id].value;
            }
            else if (field.type == "interest")
            {
                // Value for the interest field
                value = this[id].checked;
            }
            else if (field.type == "uploadfield")
            {
                // Value for the uploadfield.
                value = this[id].value;
            }
            else if (field.type == "radio_buttons")
            {
                var options = this[id];
                for (var i=0; i < options.length; i++)
                {
                    if (!options[i].checked) continue;
                    
                    value = options[i].value;
                }
            }
            else
            {
                // Value of all other inputs.
                value = this[id].value;
            }
                           
            // check if this field is required and not filled in
            if (field.required && !value)
            {
                // an error was detected
                errors.push(get_webform_error_message('required_field_missing', {field: field.label}));
                
                // continue to the next field.
                continue;
            }
            
            // check if there is a error checker waiting.
            var checker = webform_error_checkers[id];
            
            // Check if the checker is something and run it, when true returns there is nothing wrong.
            if (checker && !checker())
            {
                errors.push(get_webform_error_message(field.type+'_field_wrong', {field: field.label}));   
            }
        }

        // ok if no errors were found
        if (errors.length == 0)
        {
            // convert any date fields to the english date format.
            for (id in fields)
            {
                // Locate field.
                var field = fields[id];
                if (field.type != "date") continue;
                
                // Convert the date format.
                this[id].value = webform_convert_date(this[id].value, "english");
            }
            return true;
        }
        
        // generate error message
        var message = '';
        for (var i=0; i<errors.length; i++)
        {
            // append to message
            message += errors[i]+"\n";
        }
    
        // show error message
        alert(message);
        
        // cancel submit
        if (window.event) window.event.returnValue = false;
        return false;
    }
}

/**
 *  Function to get an error message
 *  @param  string  Identifier of the error
 *  @param  array   Associative array of variables that need to be filled in
 */
function get_webform_error_message(identifier, vars)
{
    var string = webform_error_messages[identifier];
    if (string == undefined) alert(identifier);
    for (var name in vars) string = string.replace('%'+name, vars[name]);
    return string;
}

/**
 *  Add's input control functionality to the user input.
 *  @param html object
 *  @param field object
 */
function webform_add_error_checker(element, field)
{
    switch (field.type)
    {
        case "text":
            
            break;
        case "password":

            break;
        case "email":
            webform_error_checkers[element.id] = function()
            {
                return webform_email_check(element);
            };
            break;
        case "number":
            webform_error_checkers[element.id] = function()
            {
                return webform_number_check(element);
            };
            break;
        case "date":
            webform_error_checkers[element.id] = function()
            {
                return webform_date_check(element);
            }

            // Change the date from yyyy-mm-dd to the date of the current language.
            element.value = webform_convert_date(element.value, webform_language);
            break;
            
         case "dateselect":
            webform_error_checkers[element.id] = function()
            {
                return webform_dateselect_check(element);
            }
            break;
            
        case "uploadfield":
            webform_error_checkers[element.id] = function()
            {
                return webform_upload_check(element, field);
            }
            break;
    }
}

/**
 *  This function checks if a element value is a email.
 *  @param element
 *  @return boolean
 */
function webform_email_check(element)
{   
    var value = element.value;    
    return value.match(/(^[a-zA-Z0-9._\-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$)|^$/);
}

/**
 *  This function checks if a element value is a number.
 *  @param element
 *  @return boolean
 */
function webform_number_check(element)
{   
    var value = element.value;    
    return value.match(/(^\d+$)|^$/);
}

/**
 *  This function checks if a element value is a date.
 *  @param element
 *  @return boolean
 */
function webform_date_check(element)
{
    var value = element.value;

    // When a field is empty, the answer is always true.
    if (value == "") return true;
    
    switch (webform_language)
    {
        case "english":
            return value.match(/^((19|20)\d\d)[- /.](0[0-9]|1[012]|[0-9])[- /.]([1-9]|[012][0-9]|3[01])$/);
            break;
        default:
            // The rest, dutch, german, italian, russian, greece, etc are using the europian dd-mm-yyyy style.
            return value.match(/^([1-9]|[012][0-9]|3[01])[- /.](0[0-9]|1[012]|[0-9])[- /.]((19|20)\d\d)$/);
            break;
    }
}

/**
 *  This function checks if a date select value is a date.
 *  @param element
 *  @return boolean
 */
function webform_dateselect_check(element)
{
    var value = element.value;

    var year = document.getElementById(element.id+'_year').value;
    var month = document.getElementById(element.id+'_month').value;
    var day = document.getElementById(element.id+'_day').value;
    
    if ((month == 2 || month == 4 || month == 6 || month == 9 || month == 11) && day == 31)
        return false;
    else if (month == 2 && day == 30 && year != 8228) // extra leap year
        return false;
    else if (month == 2 && day == 29 && year != 8228)
        return (new Date(year, 1, 29).getDate() == 29); // months start counting at zero
    else 
        return true;
}

/**
 *  This function checks if the uploaded file is correct.
 *  @param element
 *  @return  boolean
 */
function webform_upload_check(element, field)
{
    var value = element.value;
    
    // When a field is empty, the answer is always true.
    if (value == "") return true;
    
    // Generate file extensions based on the mimetypes.
    var extensions = new Array();
    for (var i=0; i < field.mimetypes.length; i++)
    {
        var mimetype = field.mimetypes[i];
        
        var pre = mimetype.split('/')[0];
        var post = mimetype.split('/')[1];
        
        // Find the appriopate extension for this mimetype.
        if (pre == "image")
        {
            extensions.push(post);
        }
        else if (pre == "application")
        {
            if (post.match("excel"))
            {
                extensions.push('xls');
                extensions.push('xlsx');
            }
            else if (post.match("word"))
            {
                extensions.push('doc');
                extensions.push('docx');
            }
            else if (post.match("pdf"))
                extensions.push("pdf");
            else if (post.match("zip"))
                extensions.push("zip");
        }
    }
    
    // Extract the extension of the file.
    var ext = value.slice(value.lastIndexOf('.')+1).toLowerCase();
    
    // Are we limited to extensions?
    if (extensions.length > 0)
    {
        // See if we can find the extension.
        var found = false;
        for (var i = 0; i < extensions.length; i++)
        {
            if (extensions[i] == ext) found = true;
        }
        
        // Our extension isn't found, throw a error.
        if (!found) return false;
    }
    
    // The file is correct.
    return true;
}

/**
 *  Change the format of the date from  or to yyyy-mm-dd.
 *  Use the to parameter to select the date format destination.
 *  @param string
 *  @param string
 *  @return string
 */
function webform_convert_date(date, to)
{
    // If there is no date provided, then there is nothing to do.
    if (date == "") return "";

    // The use regular expressions.
    var english = /^((19|20)\d\d)([- /.])(0[0-9]|1[012]|[0-9])[- /.]([1-9]|[012][0-9]|3[01])$/;
    var europe = /^([1-9]|[012][0-9]|3[01])([- /.])(0[0-9]|1[012]|[0-9])[- /.]((19|20)\d\d)$/;

    // The working variables.
    var matches = false;
    var year = 0;
    var month = 0;
    var day = 0;
    var separator = "-";
    
    // Is the source in europian style? DD-MM-YY
    if (matches = date.match(europe))
    {
        year = matches[4];
        separator = matches[2];
        month = matches[3];
        day = matches[1];
    }
    else if(matches = date.match(english))
    {
        year = matches[1];
        separator = matches[3];
        month = matches[4];
        day = matches[5];
    }
    
    switch (to)
    {
        case "english":
            return year+separator+month+separator+day;
        default:
            return day+separator+month+separator+year;
    }
}

/**
 *  Save the selected date to the hidden field.
 *  @param string
 *  @return string
 */
function recalculateDate(identifier)
{
    var separator = "-";
    
    // calculate the year
    var yearEl = document.getElementById(identifier+'_year');
    var selectIndex = yearEl.selectedIndex;
    var year = yearEl.options[selectIndex].text;
    
    // calculate the month
    var monthEl = document.getElementById(identifier+'_month');
    var selectIndex = monthEl.selectedIndex;
    var month = monthEl.options[selectIndex].text;
    
    // calculate the day
    var dayEl = document.getElementById(identifier+'_day');
    var selectIndex = dayEl.selectedIndex;
    var day = dayEl.options[selectIndex].text;
    
    // concat the date
    document.getElementById(identifier).value = year+separator+month+separator+day;
}

