/*
 * The Physical Initiative
 * Contact Page Javascript
 * By Kevin Dew
 * Copyright Dew Solutions 2006-2007 All Rights Reserved
 * www.dewsolutions.co.uk
 */

/*
 * Global Variables
 */

var i;
//phrases array for text that'll be displayed. Here for ease of editing
var phrases = new Array();
phrases["contactError"] = "This form could not be submit because there are errors. Please amend these and resubmit.";
phrases["nameBlank"] = "Please include your name.";
phrases["emailBlank"] = "Please include your email address.";
phrases["emailInvalid"] = "We've detected your email address is invalid. Please correct it.";
phrases["messageBlank"] = "Please include a message.";
phrases["numberBlank"] = "Please include a telephone number.";
phrases["numberInvalid"] = "We've detected your telephone number is invalid. Please correct it.";
phrases["contactPosting"] = "Submitting Request";
phrases["contactAjaxError"] = "We're very sorry but an internal error has occurred and we are unable to send your message at this time";
phrases["contactAjaxSuccess"] = "Your message has been sent, we shall do our best to reply promptly";
/*
 * DOM support check
 */
var W3CDOM = (document.createElement && document.getElementsByTagName);

/*
 * Initiate the application onload
 */
window.onload = function()
{
    //make old browsers run with no js
    if(!W3CDOM)return false;
    //set form handler
    if(id('contact_form'))id('contact_form').onsubmit = handleContact;
    return true;
}
//handle a contact form submission
//check data is ok, try submit form by ajax
function handleContact()
{
    //sanity check
    if(!id('contact_name') || !id('contact_email') || !id('contact_message') || !id('contact_send'))return true;
    //remove any old errors/status reports
    removeErrors(id('contact_fieldset'),new Array('contact','contact_name','contact_email','contact_message'));
    if(id('contact_ajax_status'))id('contact_form').removeChild(id('contact_ajax_status'));
    if(id('contact_ajax_result'))id('contact_fieldset').removeChild(id('contact_ajax_result'));
    
    //assume we havent got an error
    var gotError = false;

    //function for handling an error
    //sets var to show we have an error and runs insertError function to put it
    //on the web page
    function setError()
    {
        gotError = true;
        insertError(phrases["contactError"],id('contact_fieldset'),id('contact_name_label'),'contact_err');

    }

    //function to test an email address
    //string input of the email address
    function testEmail(email)
    {
        var regExp = /^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]{1,64}@([a-z0-9.!\#$%&\'*+-/=?^_`{|}~]){1,255}$/i;
        if(!regExp.test(email)) return false;
        var emailParts = email.split("@");
        //check email doesn't have dots at the start of domain bit
        regExp = /^[^\.](.+)[^\.]$/;
        if(!regExp.test(emailParts[1])) return false;
        //check we have atleast two parts (like yahoo.com)
        var domainParts = emailParts[1].split(".");
        if(domainParts.length < 2) return false;
        return true;
    }

    //check name isn't empty
    trimFormField(id('contact_name'));
    if(id('contact_name').value == '')
    {
        //name empty
        setError();
        id('contact_name').className = 'input_err';
        insertError(phrases["nameBlank"],id('contact_fieldset'),id('contact_name_label'),'contact_name_err');
        id('contact_name').focus;
    }

    //check email isn't empty
    trimFormField(id('contact_email'));
    if(id('contact_email').value == '')
    {
        if(!gotError)setError();
        id('contact_email').className = 'input_err';
        insertError(phrases["emailBlank"], id('contact_fieldset'),id('contact_email_label'),'contact_email_err');
        if(!gotError)id('contact_email').focus;
    }

    //check email isn't invalid
    if(id('contact_email').value != '' && !testEmail(id('contact_email').value))
    {
        if(!gotError)setError();
        id('contact_email').className = 'input_err';
        insertError(phrases["emailInvalid"], id('contact_fieldset'),id('contact_email_label'),'contact_email_err');
        if(!gotError)id('contact_email').focus;
    }

    //check message isn't empty
    trimFormField(id('contact_message'));
    if(id('contact_message').value == '')
    {
        if(!gotError)setError();
        id('contact_message').className = 'input_err';
        insertError(phrases["messageBlank"], id('contact_fieldset'),id('contact_message_label'),'contact_message_err');
        if(!gotError)id('contact_message').focus;
    }

    if(gotError)return false;
    
    //try create ajax class
    try
    {
        var ajax = new ajaxClass();
        if(!ajax.canAjax)return true;
    }catch(e)
    {
        //can't use ajax submit form old way
        return true;
    }

    //make page look like it's doing stuff, stop a user editing form
    id('contact_fieldset').className = "in_progress";
    var disableFields = new Array('contact_name','contact_email','contact_message','contact_send');
    for(i=0;i<disableFields.length;i++)
        id(disableFields[i]).disabled = true;

    appendText(phrases["contactPosting"],id('contact_fieldset'),"contact_ajax_status");

    //create data string
    var formData = "contact_name="+escape(id('contact_name').value)+
                   "&contact_email="+escape(id('contact_email').value)+
                   "&contact_message="+escape(id('contact_message').value);

    var ajaxState = function(){
        //function to undisable fields
        function showFields()
        {
            id('contact_fieldset').className = '';
            var disableFields = new Array('contact_name','contact_email','contact_message','contact_send');
            for(i=0;i<disableFields.length;i++)
                id(disableFields[i]).disabled = false;
        }
        //function to submit form the old way
        function submitForm()
        {
            showFields();
            id('contact_form').submit();
        }
        //function to remove the ajax status message and show the result of
        //the ajax request
        function showResult(phrase)
        {
            //hide ajax status
            id('contact_fieldset').removeChild(id('contact_ajax_status'));
            appendText(phrase,id('contact_fieldset'),"contact_ajax_result");

        }
        //if HTTP request isn't complete
        if (ajax.XMLHttp.readyState != 4) return;
        try
        {
            //get the ajax status (in a try because it sometimes causes errors)
            var ajaxStatus = ajax.XMLHttp.status;
        }
        catch(e)
        {
            //on error clear the timeout and submit the form
            if(timer)clearInterval(timer);
            submitForm();
            return;
        }
        //ajax request complete
        if (ajaxStatus == 200)
        {

            if(timer)clearInterval(timer);
            try
            {
                //try get the response from the XML. could cause errors
                var response = ajax.XMLHttp.responseXML;
                var success = response.getElementsByTagName("success")[0].firstChild.nodeValue
                
            }
            catch(e)
            {
                submitForm();
                return;
            }
            //check the value of the success message
            switch(success)
            {
              case "0":
                //internal error
                id('contact_ajax_status').className = "int_err";
                showResult(phrases["contactAjaxError"]);
                break;
              case "1":
                //backend is confused so letting the form submit normally to resolve it
                //typically caused when there's a disagreement about validation (i.e passes in js, fails in php)
                submitForm();
                break;
              case "2":
                //actual success
                id('contact_ajax_status').className = "success";
                id('contact_name').value = "";
                id('contact_email').value = "";
                id('contact_message').value = "";
                showResult(phrases["contactAjaxSuccess"]);
                break;
            }

            showFields();
        }
        else
        {
            //clear timeout first
            if(timer)clearInterval(timer);
            //we've got some sort of fail, let the form submit normally so least it doesnt look dead.
            submitForm();
        }
    }
    //function for aborting the ajax request
    var ajaxTimeout = function()
    {
        try
        {
            ajax.XMLHttp.abort();
        }
        catch(e){
            submitForm();
        }
    }
    var timer = setInterval(ajaxTimeout, 10000);
    //submit request
    ajax.postRequest("ajax.php",ajaxState,formData);
    //don't submit form
    return false;
}

/*
function to insert an error into the web page.
arguments are:
phrase: the string defined at start of this to use as the error text
holder: the element (not the id) that we want to be parent to this error
before: the element of what we want this error added before
id: the id of the new element we're creating
*/
function insertError(phrase, holder, before, id)
{
    holder.insertBefore(newP(id,"error",phrase),before);
}
//function to add text to an element using the phrase string, a holder element
//and a string of the id of this new text
function appendText(phrase,holder,id)
{
    holder.appendChild(newP(id,'',phrase));
}
//function to create a new P element, of a specified id, in a certain class with
//certain text
function newP(id,className,phrase)
{
    var newP = document.createElement("p");
    newP.id = id;
    newP.className = className;
    newP.appendChild(document.createTextNode(phrase))
    return newP;
}
//function to remove all error objects inside an element (holder)
//and to change the class of all input elements in an array (specified by id) to the input class
function removeErrors(holder, idArray)
{
    for(i=0;i<idArray.length;i++)
    {
        var err;
        if(err = id(idArray[i]))
        {
            err.className = 'input';
        }
        if(err = id(idArray[i] + '_err'))
        {
            holder.removeChild(err);
        }
    }
}
//function to trim the data in a form field
function trimFormField(formObject)
{
    formObject.value = trim(formObject.value);
}

