/********************
***** Ajax Core *****
********************/

// return Ajax object
function ajaxObject() {
  var ajaxRequest;  // infamous Ajax variable
  var error;  // error object

  // browser support code
  try { ajaxRequest = new XMLHttpRequest(); /* Opera 8.0+, Firefox, Safari */ }
  catch(error) {
    try { ajaxRequest = new ActiveXObject('Msxml2.XMLHTTP'); /* IE browsers */ }
    catch(error) {
      try { ajaxRequest = new ActiveXObject('Microsoft.XMLHTTP'); /* other supported browsers */ }
      catch(error) {
        // no Ajax support
        alert('Your browser does not support Ajax!');
        ajaxRequest = false;  // Ajax failure
      }
    }
  }

  return ajaxRequest;  // return Ajax object/failure
}

// submit via Ajax
function ajaxSend(ajaxRequest, uri, qs) {
  // request data from the server via Ajax
  ajaxRequest.open('POST', uri, true);
  ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  ajaxRequest.send('ajax=true'+(qs!=''?'&'+qs:''));
}

// build query string for Ajax
function buildQS(formID) {
  var qs = '';
  var frm = document.getElementById(formID);  // get form object
  for(var j=0; j<frm.length; j++)  // loop through form elements
    if(frm.elements[j].name && (frm.elements[j].type!='checkbox' || (frm.elements[j].type=='checkbox' && frm.elements[j].checked)))  // element has a name and isn't a checkbox or is checked
      qs += (qs.length?'&':'') + escape(frm.elements[j].name) + '=' + escape(frm.elements[j].type=='checkbox'?(frm.elements[j].value?frm.elements[j].value:'on'):frm.elements[j].value);  // add key/value pair
  return qs;
}

/*************************
***** Ajax Functions *****
*************************/

// fill given container with Ajax results
function ajaxCallback(qs) {
  var ajaxRequest = ajaxObject();  // get Ajax object
  if(!ajaxRequest) return false;  // Ajax failed to start

  // receive data from server via Ajax when complete
  ajaxRequest.onreadystatechange = function() {
    if(ajaxRequest.readyState==4)  // Ajax request completed
      ajaxParseResponse(ajaxRequest.responseText);  // send results to pre-defined ajaxParseResponse()
  }

  // request data from the server via Ajax
  ajaxSend(ajaxRequest, window.location.href, qs);
}

// fill given container with Ajax results, submitting to self
function ajaxSelf(containerID, qs, seamless) {
  var ajaxRequest = ajaxObject();  // get Ajax object
  if(!ajaxRequest) return false;  // Ajax failed

  // set processing circle
  if(!seamless)  // if flagged as seamless, then don't show processing circle
    document.getElementById(containerID).innerHTML = '<p class="center"><img src="/images/processing-circle.gif" />&nbsp; <span id="'+containerID+'-status">Sending request...<\/span><\/p>';

  // receive data from server via Ajax when complete
  ajaxRequest.onreadystatechange = function() {
    switch(ajaxRequest.readyState) {
      case 1:  // loading
        if(document.getElementById(containerID+'-status'))
          document.getElementById(containerID+'-status').innerHTML = 'Processing request...';
        break;
      case 2:  // loaded
      case 3:  // interative
        if(document.getElementById(containerID+'-status'))
          document.getElementById(containerID+'-status').innerHTML = 'Updating screen...';
        break;
      case 4:  // complete
        document.getElementById(containerID).innerHTML = ajaxRequest.responseText;
        formInit();  // initialize first form
    }
  }

  ajaxSend(ajaxRequest, window.location.href, qs);  // request data from the server via Ajax

  return true;  // Ajax succeeded
}

// fill given container with Ajax results, submitting to self
function ajaxSubmit(containerID, formID, seamless) {
  return ajaxSelf(containerID, buildQS(formID), seamless);  // request data from the server via Ajax
}

/************************
***** Auto-complete *****
************************/

// set value to auto-complete selection
function autocompleteSelect(inputID, value, formID) {
  document.getElementById(inputID).value = value;  // set value of input with selected value
  autocompleteToggle(inputID);  // toggle visibility of auto-complete box
  if(formID!=undefined) formSubmit(formID);  // submit form

  return false;  // don't follow link
}

// toggle auto-complete box
function autocompleteToggle(inputID, qs) {
  var containerID = inputID+'_complete';  // auto-complete results container

  if(qs!=undefined && document.getElementById(inputID).value.length>2) {  // get auto-complete suggestions, display them
    var ajaxRequest = ajaxObject();  // get Ajax object
    if(!ajaxRequest) return false;  // Ajax failed to start

    // receive data from server via Ajax when complete
    ajaxRequest.onreadystatechange = function() {
      if(ajaxRequest.readyState==4) {  // request complete
        document.getElementById(containerID).innerHTML = ajaxRequest.responseText;  // set container contents
        document.getElementById(containerID).style.display = ajaxRequest.responseText!='' ? '' : 'none';  // if has contents then display box, otherwise hide it
      }
    }

    // request data from the server via Ajax
    ajaxSend(ajaxRequest, window.location.href, 'complete='+escape(document.getElementById(inputID).value)+(qs?'&'+qs:''));
  }
  else  // hide suggestions
    document.getElementById(containerID).style.display = 'none';
}

// hide any auto-complete divs
function autocompleteHideAll() {
  var divs = document.getElementsByTagName('div');  // get all divs
  for(j=0; j<divs.length; j++)  // loop through divs
    if(divs[j].id.indexOf('_complete')!=-1)  // is an auto-complete div
      divs[j].style.display = 'none';  // hide div
}

/***************
***** Form *****
***************/

// select first element in given form
function formInit(formID) {
  var frm = (typeof(formID)!='string')?document.forms[0]:document.getElementById(formID);  // get specified/first form

  // select first blank element
  if(frm)  // form exists
    for(j=0; j<frm.elements.length; j++)
      if(frm.elements[j].type=='checkbox'?!frm.elements[j].checked:frm.elements[j].value=='') {
        frm.elements[j].focus();
        break;
      }
}

// submit form (contents of given form ID)
function formSubmit(formID, forgoAjax, containerID) {
  var frm = document.getElementById(formID);  // get form object

  autocompleteHideAll();  // hide all auto-complete divs

  // check for errors
  var errors = '';  // init errors
  for(j=0; j<frm.elements.length; j++)  // loop through form elements
    if(frm.elements[j].name!='')
      if(frm.elements[j].className=='required' && (frm.elements[j].type=='checkbox'?!frm.elements[j].checked:frm.elements[j].value==''))
        errors += "\n  * "+(frm.elements[j].title?frm.elements[j].title:(frm.elements[j].name).replace(/^(.)|\s(.)/g, function ($1) { return $1.toUpperCase(); } ));

  if(errors) {  // has errors
    alert('You must fill in the following to continue:'+errors);  // display errors
    formInit(formID);  // initialize form
    return false;  // don't submit form
  }
  else if(forgoAjax)  // don't use Ajax
    return true;  // submit form normal way
  else  // attempt Ajax
    return !ajaxSubmit(containerID?containerID:'ajax', formID);  // submit via Ajax, returning results
}

// click submit button on "enter" keypress
function submitOnEnter(evt, formID) {
  if((window.event && evt.keyCode==13) || (evt.which && evt.which==13)) {  // IE and others (13 is ASCII for Enter key)
    this.blur();  // drop focus (just in case there are onBlur events)
    formSubmit(formID);  // submit form
  }
}

window.onload = formInit;  // initialize first form on page load