function MultiForm()
{

  this.TargetField = false;
  this.ParentField = false;
  this.ValueDefault = false;
  this.AjaxURL = false;
  this.AjaxEvalURL = false;
  this.FetchData = FetchDataFunction;
  this.ValueSelected = false;
  this.OnloadTarget = false;
  this.OnloadEval = false;
  this.ParentAllowNull = false;
  this.ParentFieldNull = true;
  this.ParentAllowNullTarget = false;
  this.StaticData = false;
  this.SelectText = true;
  this.DebugMode = false;
  this.CaseInsensitive = false;
  this.DisableAllChildren = DisableAllChildrenFunction;
  this.OutputHandlerFunction = 'FetchDataCallback';
  this.SelectHeading = false;
  this.SelectHeadingDividerLeft = '----- '; // Space After
  this.SelectHeadingDividerRight = ' -----'; // Space Before
  this.SelectHeadingTextUnavailable = 'No Options Available'; // When Search results return nothing
  this.AutoSelectSingularOptions = false;
  this.MasterAllowNull = true;
  this.MasterTarget = false;
  this.MasterObject = null;
  this.ForkedAjax = null;

  this.FetchString = '';
  this.FetchStringCSV = '';
  this.FetchDataJson = null;
  this.FetchInitiator = false; // original object that started the chain
  this.FetchCSVMode = false;

  this.FetchStringCSVFunction = FetchStringCSVFunction;
  
  function ParentFieldNullChecker(input)
  {
    var array = input.split(',');
    var valid = 0;
    for (var i = 0;i < array.length;i++)
    {
      if(document.getElementById(array[i]).value)
      {
        valid++;
      }
    }
    if(valid == array.length)
    {
      return false
    }
    else
    {
      return true;
    }
  }

  function FetchDataFunction(TriggerMode)
  {
    if(this.DebugMode)alert('FetchData function called ('+this.TargetField+')'); // DEBUG OUTPUT
    var x = document.getElementById(this.TargetField);
    if(typeof x == 'undefined' || x == null)
    {
      alert('Failed to locate HTML element with the ID: '+this.TargetField+', Please contact Dealer Solutions');
    }

    // If this.ValueDefault is set and were changing it to blank then we need to start re-load the current element
    if(this.ValueDefault != false && x.value != true)
    {
      //this.ValueDefault = false;
      //this.FetchData();
      //return false;
    }
    // If this.ValueDefault is set and were changing it to blank then we need to start re-load the current element

    var MatchFound = false;
    if(this.ParentAllowNullTarget)
    {
      this.ParentFieldNull = ParentFieldNullChecker(this.ParentAllowNullTarget);
      if(this.ParentFieldNull == true)
      {
        if(this.DebugMode)alert('ParentFieldValue is FALSE'); // DEBUG OUTPUT
        this.ParentFieldValue = null;
      }
      else
      {
        if(this.DebugMode)alert('ParentFieldValue is TRUE'); // DEBUG OUTPUT
        this.ParentFieldValue = true;
      }
    }
    else if(this.ParentField)
    {
      this.ParentFieldValue = document.getElementById(this.ParentField).value;
      if(this.DebugMode)alert('ParentFieldValue is:' + this.ParentFieldValue); // DEBUG OUTPUT
    }

    // Disables all child objects
    x.disabled = true;
    this.DisableAllChildren(this,TriggerMode);
    this.FetchStringCSVFunction(this,this);
    if(this.AjaxEvalURL)
    {
      if(this.FetchStringCSV)
      {
        this.FetchString = FetchStringCSVFunction_URLHelper('fetch',eval(this.AjaxEvalURL),TriggerMode);
        this.FetchCSVMode = true;
        if(this.DebugMode)alert('FetchString: ' + this.FetchString + ' / FetchStringCSV: ' + this.FetchStringCSV); // DEBUG OUTPUT
      }
      //prompt(this.AjaxURL,this.AjaxURL);
    }

    // fetch mater object
    if(this.MasterTarget != false && this.MasterAllowNull != true)
    {
      this.MasterObject = eval(this.MasterTarget);
    }

    if (((this.ParentFieldValue != null && this.ParentFieldValue != '') || this.ParentAllowNull == true) && this.StaticData == false && (this.MasterAllowNull == true || this.MasterTarget == false || (this.MasterTarget != false && this.MasterAllowNull != true && this.MasterObject.ValueDefault != null && this.MasterObject.ValueDefault != '')))
    {
      if(this.DebugMode)alert('Preparing to FORK.Ajax'); // DEBUG OUTPUT
      if (x.type == "select" || x.type == "select-one")
      {
        x.options.length = 1;
        x.options[0] = new Option(this.SelectHeadingDividerLeft+'Loading: Please Wait'+this.SelectHeadingDividerRight,'');
        x.selectedIndex = 0;
      }
      if(this.FetchCSVMode == true && this.FetchDataJson)//document.getElementById('json_container').value != '')
      {
        FetchDataCallback(this.FetchDataJson,this,TriggerMode);
      }
      else
      {
        this.FetchDataJson = null;
        if(this.FetchStringCSV && this.FetchCSVMode)
        {
          //this.AjaxEvalURL = this.AjaxEvalURL + '+\'&fetch_csv=' + this.FetchStringCSV + '\'';
          //this.AjaxURL = eval(this.AjaxEvalURL);
          this.AjaxURL = eval(this.AjaxEvalURL + '+\'&fetch_csv=' + this.FetchStringCSV + '\'');
          if(this.DebugMode)alert('AjaxEvalURL: '+this.AjaxURL); // DEBUG OUTPUT
          // RESET the fetch
          this.FetchStringCSV = false;
        }
        // URL ENCODE
        this.AjaxURL = this.AjaxURL.replace('+','%2B');

        // abort existing forks
        if(this.ForkedAjax != null)
        {
          this.ForkedAjax.abort();
        }

        this.ForkedAjax = new FORK.Ajax("GET", this.AjaxURL,
          {
            timeout: 30000,
            argument: {TargetObject: this},
            onComplete: function(o,x)
            {
              if(x.DebugMode)alert('FORK OnComplete Called'); // DEBUG OUTPUT
              eval(x.TargetObject.OutputHandlerFunction + '(o,x.TargetObject,\''+TriggerMode+'\')');
              //FetchDataCallback(o,x.TargetObject);//, x.TargetField , x.ParentField, x.ValueSelected , x.ValueDefault, x.OnloadTarget);
            }
          }
        );
      }
    }
    else if ((this.StaticData == true && this.ParentField == false && this.ParentAllowNullTarget == false) || (this.StaticData == true && this.ParentFieldValue && (this.ParentField || this.ParentAllowNullTarget)))// && this.ValueDefault)
    {
      if(this.DebugMode)alert('Parent is Null, no Ajax Call being made'); // DEBUG OUTPUT
      x.disabled = false;
      for (var xi = 0;xi < x.length;xi++)
      {
        if (xi == 0 && x[xi].value == '' && (x[xi].text == '' || x[xi].text == this.SelectHeadingDividerLeft+this.SelectHeadingTextUnavailable+this.SelectHeadingDividerRight))
        {
          if (this.SelectHeading == false)
          {
            x.options[0] = new Option(this.SelectHeadingDividerLeft+'Please Select'+this.SelectHeadingDividerRight,'');
          }
          else
          {
            x.options[0] = new Option(this.SelectHeadingDividerLeft+this.SelectHeading+this.SelectHeadingDividerRight,'');
          }
        }
        if (x[xi].value == this.ValueDefault || (this.CaseInsensitive == true && x[xi].value.toLowerCase() == this.ValueDefault.toLowerCase()))
        {
          if(this.DebugMode && this.CaseInsensitive == true)alert('Match Found (case insensitive)'); // DEBUG OUTPUT
          if(this.DebugMode && this.CaseInsensitive == false)alert('Match Found (case sensitive)'); // DEBUG OUTPUT
          x.selectedIndex = xi;
          var MatchFound = true;
        }
      }
      if (this.OnloadEval && (this.ParentAllowNull == true || MatchFound == true))
      {
        if(this.DebugMode)alert('OnloadEval (A) called\n----------\n'+this.OnloadEval); // DEBUG OUTPUT
        eval(this.OnloadEval)
      }
      else
      {
        //document.getElementById('json_container').value = '';
      }
      if (this.OnloadTarget && (this.ParentAllowNull == true || MatchFound == true))
      {
        var PeformTarget = eval(this.OnloadTarget);
        if (PeformTarget.ValueDefault || this.ValueDefault)
        {
          if(this.DebugMode)alert('OnloadTarget (B) ('+this.OnloadTarget+') function called'); // DEBUG OUTPUT
          PeformTarget.FetchDataJson = this.FetchDataJson; // PASS THE DATA TO THE CHILD
          this.FetchDataJson = null;
          PeformTarget.FetchData();
        }
      }
      else
      {
        //document.getElementById('json_container').value = '';
      }
    }
    // JUNE WORK
    else
    {
      if (this.OnloadEval)
      {
        if(this.DebugMode)alert('OnloadEval (1) called\n----------\n'+this.OnloadEval); // DEBUG OUTPUT
        eval(this.OnloadEval)
      }
      else if(this.OnloadTarget)
      {
        var PeformTarget = eval(this.OnloadTarget);
        if(this.DebugMode)alert('OnloadTarget (1) ('+this.OnloadTarget+') function called'); // DEBUG OUTPUT
        PeformTarget.FetchDataJson = this.FetchDataJson; // PASS THE DATA TO THE CHILD
        this.FetchDataJson = null;
        PeformTarget.FetchData();
      }
      else
      {
        //document.getElementById('json_container').value = '';
      }
    }
    // JUNE WORK
  }
  
  function DisableAllChildrenFunction(TargetObject,TriggerMode)
  {
    if (TargetObject)
    {
      //if(TargetObject.DebugMode)alert('Disabling Children'); // DEBUG OUTPUT
      var x = document.getElementById(TargetObject.TargetField);
      if ((TargetObject.StaticData == false && typeof x != 'undefined') || (TargetObject.StaticData == true && TargetObject.ParentAllowNull == false && TargetObject.ParentField))
      {
        if (TargetObject.SelectText)
        {
          if (TargetObject.StaticData == true)
          {
            if(x.options[0].value == '')
            {
              x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeadingTextUnavailable+TargetObject.SelectHeadingDividerRight,'');
            }
          }
          else if (x && x.options)
          {
            x.options.length = 1;
            x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeadingTextUnavailable+TargetObject.SelectHeadingDividerRight,'');
          }
        }
        if(x)
        {
          x.selectedIndex = 0;
          x.disabled = true;
        }
      }
      else if (x)
      {
        x.disabled = false;
      }
      // reset default value
      var OnloadTarget = eval(TargetObject.OnloadTarget);
      if(TriggerMode != 'onload')
      {
        OnloadTarget.ValueDefault = null;
      }
      OnloadTarget.FetchDataJson = null;
      DisableAllChildrenFunction(OnloadTarget,TriggerMode);
    }
  }

  function FetchDataCallback(XMLHttpRequest,TargetObject,TriggerMode)
  {
    if(TargetObject.DebugMode)alert('FetchDataCallback function called'); // DEBUG OUTPUT

    // reset the fork object since it got this far
    TargetObject.ForkedAjax = null;

    // SWITCH TO DETERMIN DATA SOURCE
    if(TargetObject.FetchCSVMode == true && TargetObject.FetchDataJson != null)//document.getElementById('json_container').value != false)
    {
      var data = eval(XMLHttpRequest);//document.getElementById('json_container').value);
      //alert('A:'+TargetObject.FetchDataJson);
    }
    else if(TargetObject.FetchCSVMode == true)
    {
      //alert('source b');
      var data = eval(XMLHttpRequest.responseText);
      //document.getElementById('json_container').value = XMLHttpRequest.responseText;
      TargetObject.FetchDataJson = XMLHttpRequest.responseText;
      //alert('B:'+TargetObject.FetchDataJson);
    }
    else
    {
      //alert('source c');
      TargetObject.FetchDataJson = XMLHttpRequest.responseText;
      var data = eval(XMLHttpRequest.responseText);
      //alert('C:'+TargetObject.FetchDataJson);
    }

    var MatchFound = false;
    var x = document.getElementById(TargetObject.TargetField);

    // HOOK INTO NEW METHOD
    if(TargetObject.FetchCSVMode == true && typeof TargetObject.FetchString != 'undefined' && TargetObject.FetchString != false)
    {
      if(typeof data == 'undefined')
      {
        return false;
      }
      else if(typeof data[0] != 'undefined' && typeof data[0][TargetObject.FetchString] != 'undefined')
      {
        data = data[0][TargetObject.FetchString];
      }
      else if(typeof data[TargetObject.FetchString] != 'undefined')
      {
        data = data[TargetObject.FetchString];
      }
      // RESET VARS
      TargetObject.FetchString = false;
      TargetObject.FetchCSVMode = false
    }
    // HOOK INTO NEW METHOD

    /*
    // If the Parent is blank, reset the child
    if (TargetObject.ParentField && TargetObject.ParentAllowNull == false)
    {
      if (document.getElementById(TargetObject.ParentField).value)
      {
        // Do Nothing
      }
      else
      {
        if (TargetObject.SelectText)
        {
          x.options.length = 1;
          x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeadingTextUnavailable+TargetObject.SelectHeadingDividerRight,'');
        }
        // Duplication of OnloadTargetFromBelow
        if (TargetObject.OnloadTarget)
        {
          var PeformTarget = eval(TargetObject.OnloadTarget);
          PeformTarget.FetchData();
        }
        if(TargetObject.DebugMode)alert('Returning'); // DEBUG OUTPUT
        return;
      }
    }
    */
    // Make Level
    x.options.length = 1;
    if (data.length > 0)
    {
      if(TargetObject.DebugMode)alert('Data Found'); // DEBUG OUTPUT
      if (data.length)
      {
        if (TargetObject.SelectText == true)
        {
          if (TargetObject.SelectHeading == false)
          {
            x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+'Please Select'+TargetObject.SelectHeadingDividerRight,'');
          }
          else
          {
            x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeading+TargetObject.SelectHeadingDividerRight,'');
          }
          var indexmodifyer = 1;
        }
        else
        {
          var indexmodifyer = 0;
        }
        if(TargetObject.DebugMode)alert('FetchDataCallback - Loop Initiated'); // DEBUG OUTPUT
        for (var xi = 0;xi < data.length;xi++)
        {
          // it MUST have an data[xi].attribute_name
          if (data[xi].attribute_name && data[xi].attribute_count > 0)
          {
            x.options[xi + indexmodifyer] = new Option((data[xi].attribute_text) ? data[xi].attribute_text + ' (' + data[xi].attribute_count + ')' : data[xi].attribute_name + ' (' + data[xi].attribute_count + ')',data[xi].attribute_name);
          }
          else if(data[xi].attribute_name)
          {
            x.options[xi + indexmodifyer] = new Option((data[xi].attribute_text) ? data[xi].attribute_text : data[xi].attribute_name,data[xi].attribute_name);
          }
          else
          {
            indexmodifyer--; // remove one from the index
          }
          if(TargetObject.DebugMode && TargetObject.AutoSelectSingularOptions && data.length == 1)alert('Only one result found, auto selecting'); // DEBUG OUTPUT
          if ((TargetObject.AutoSelectSingularOptions && data.length == 1) || (TargetObject.ValueDefault && data[xi].attribute_name && data[xi].attribute_name == TargetObject.ValueDefault) || (TargetObject.CaseInsensitive == true && data[xi].attribute_name.toLowerCase() && data[xi].attribute_name.toLowerCase() == TargetObject.ValueDefault.toLowerCase()))
          {
            if(TargetObject.DebugMode && TargetObject.CaseInsensitive == true)alert('Match Found (case insensitive)'); // DEBUG OUTPUT
            if(TargetObject.DebugMode && TargetObject.CaseInsensitive == false)alert('Match Found (case sensitive)'); // DEBUG OUTPUT
            x.selectedIndex = xi + indexmodifyer;
            TargetObject.ValueDefault = data[xi].attribute_name;
            var MatchFound = true;
          }
        }
        x.disabled = false;
      }
      else if (TargetObject.SelectHeadingTextUnavailable)
      {
        x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeadingTextUnavailable+TargetObject.SelectHeadingDividerRight,'');
        x.disabled = true;
      }
    }
    else if (TargetObject.SelectHeadingTextUnavailable)
    {
      if(TargetObject.DebugMode)alert('Data Not Found'); // DEBUG OUTPUT
      x.options[0] = new Option(TargetObject.SelectHeadingDividerLeft+TargetObject.SelectHeadingTextUnavailable+TargetObject.SelectHeadingDividerRight,'');
      x.disabled = true;
    }
    else
    {
      if(TargetObject.DebugMode)alert('Data Not Found'); // DEBUG OUTPUT
    }
    if (TargetObject.OnloadEval)
    {
      if(this.DebugMode)alert('OnloadEval (2) called\n----------\n'+TargetObject.OnloadEval); // DEBUG OUTPUT
      eval(TargetObject.OnloadEval);
    }
    /*
    if (TargetObject.OnloadTarget)
    {
      var PeformTarget = eval(TargetObject.OnloadTarget);
      if(PeformTarget && (PeformTarget.ParentAllowNull == true || MatchFound == true))
      {
        if(TargetObject.DebugMode)alert('FetchDataCallback - Trying Onload Target ('+TargetObject.OnloadTarget+')'); // DEBUG OUTPUT
        var PeformTarget = eval(TargetObject.OnloadTarget);
        //if (PeformTarget.ValueDefault || TargetObject.ValueDefault)
        if(PeformTarget.ParentAllowNull == true || MatchFound == true || TargetObject.ValueDefault || PeformTarget.ValueDefault) // || TargetObject.ParentAllowNull == true
        {
            if(TargetObject.DebugMode)alert('OnloadTarget (2) ('+TargetObject.OnloadTarget+') function called'); // DEBUG OUTPUT
            PeformTarget.FetchData();
        }
      }
    }
    */
    if (TargetObject.OnloadEval)
    {
      if(TargetObject.DebugMode)alert('OnloadEval (1) called\n----------\n'+TargetObject.OnloadEval); // DEBUG OUTPUT
      eval(TargetObject.OnloadEval)
    }
    else if (TargetObject.OnloadTarget)
    {
      var PeformTarget = eval(TargetObject.OnloadTarget);
      if(TargetObject.DebugMode)alert('OnloadTarget (1) ('+TargetObject.OnloadTarget+') function called'); // DEBUG OUTPUT
      PeformTarget.FetchDataJson = TargetObject.FetchDataJson; // PASS THE DATA TO THE CHILD
      TargetObject.FetchDataJson = null;
      PeformTarget.FetchData(TriggerMode);
    }
    else
    {
      TargetObject.FetchDataJson = null; // CLEARS THIS JSON
    }
  } //FetchDataCallback()

    function FetchStringCSVFunction(TargetObject,ParentObject)
    {
      if (TargetObject)
      {
        // grab all the fetch=blah out of the URL line 
        // TargetObject.AjaxURL
        var FetchString = FetchStringCSVFunction_URLHelper('fetch',eval(TargetObject.AjaxEvalURL))
        if(FetchString && ParentObject.FetchStringCSV)
        {
          ParentObject.FetchStringCSV = ParentObject.FetchStringCSV + ',' + FetchString;
        }
        else if(FetchString)
        {
          ParentObject.FetchStringCSV = FetchString;
        }
        if(typeof TargetObject.OnloadTarget != 'undefined')
        {
          FetchStringCSVFunction(eval(TargetObject.OnloadTarget),ParentObject);
        }
      }
    }  
    function FetchStringCSVFunction_URLHelper(name,url)
    {
      name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
      var regexS = "[\\?&]" + name + "=([^&#]*)";
      var regex = new RegExp(regexS);
      var results = regex.exec(url);
      if(results == null)
        return "";
      else
        return decodeURIComponent(results[1].replace(/\+/g, " "));
    }

} // MultiForm()
