  /* form-functions.js --- 2007-07 CH */
  String.prototype.prepare = function() {
    var rexp = /^(.*)[^-a-zA-z0-9'"]+(.*)$/;
    var str = this;
    while (rexp.test(str)) {
      str = str.replace(rexp, "$1$2");
    }
    return str;
  }

  String.prototype.trimAll = function () {
    return this.replace(/^\s*([\w]*.*[\w]*)\s*$/g, "$1");
  }
  
  String.prototype.trimEnds = function() {
    var whtSpEnds = new RegExp("^\\s*|\\s*$", "g");
    return this.replace(whtSpEnds, "");   // Remove leading or trailing white space.
  }

  var formNames, formValues, serNames, serValues;
  var fieldData = new Object();
   
  var formFunctions = {
    xmlhttp: null,
    axUrl: '',
    axQstr: '',
    axTransportType: '',
    activeFormID: '',
    cuid: '',
    isStandalone: false,
    isValidUser: false,
    isNewUser: true,
    targetID: '',
    userName: '',
    userFirstName: '',
    
    get_product: function() {
      switch(location.hostname) {
        case 'planit.cuna.org':
          return 'PLAN'; break;
        case 'moneymix.cuna.org':
          return 'MMIX'; break;
        default:
          return '';
      }
    },

    get_countdown: function(id) {
      this.toString = function() { return 'get_countdown'; }
      this.targetID = id;
      var url = "/include/getPlanCountdown.php";
//alert('IN GET COUNTDOWN. URL = ' + url);
//document.writeln('IN GET COUNTDOWN. URL = ' + url);   
      this.xmlhttp = null;
      try { // IE
        this.xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
      } catch (err) {
        try {
          this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (err) {
          this.xmlhttp = null;
        }
      }
      // FF
      if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
        this.xmlhttp = new XMLHttpRequest();
      }
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.get_countdown_response();
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }
    },
    
    get_countdown_response: function() {
      var _response;
      var target = (this.targetID) ? document.getElementById(this.targetID) : null;
      if (!target) { return; }
      if (4==this.xmlhttp.readyState && 200==this.xmlhttp.status) {
        _response = new String(this.xmlhttp.responseText);
//alert("82 GET DATA RESPONSE TEXT: |" + _response + '|');
        if (2 < _response.length) {
          target.innerHTML = _response;
        }
      }
      return;
    },

    make_xmlhttp_client: function() {
      this.xmlhttp = null;
      try { // IE
        this.xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
      } catch (err) {
        try {
          this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (err) {
          this.xmlhttp = null;
        }
      }
      // FF
      if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
        this.xmlhttp = new XMLHttpRequest();
      }
      return this.xmlhttp;
    },

    /* begin xmlhttp "member" functions */

    setCallback: function(sFunc) {
      if ('undefined' != typeof this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          eval(sFunc);
        }
      }
    },

    setUrl: function(sUrl) {
      this.axUrl = sUrl;
    },

    setQstr: function(sQstr) {
      this.axQstr = escape(encodeURIComponent(sQstr));
    },

    setTransportType: function(sType) {
      if ('GET'==sType || 'POST'==sType) {
        this.axTransportType = sType;
      }
    },

    transmit: function() {
      // THROWS ERROR: 'undefined' != typeof this.xmlhttp.onreadystatechange 
      if ('null' != typeof this.onreadystatechange
        && '' != this.axUrl
        && '' != this.axTransportType) {
        switch (this.axTransportType) {
          case 'GET':
           if ('' == this.axQstr) {
             return false;
           }
           uri = this.axUrl + "?" + this.axQstr;
           try {
             this.xmlhttp.open(this.axTransportType, uri, true);
           } catch(err) {
             alert('ERROR: ' + err);
           }
           if (window.ActiveXObject) {
             this.xmlhttp.send();
           } else if (window.XMLHttpRequest) {
             this.xmlhttp.send(null);
           }
           break;
             
          case 'POST':
           if (0 < arguments.length) {
             parameters = arguments[0]; //escape(arguments[0]);
           } else {
             parameters = '<no data>';
           }
           this.xmlhttp.open(this.axTransportType, this.axUrl, true);
	   this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	   this.xmlhttp.setRequestHeader("Content-length", parameters.length);
	   this.xmlhttp.setRequestHeader("Connection", "close");
	   this.xmlhttp.send(parameters);
           break;
        } // switch
      }
    },

    /* end xmlhttp "member" functions */

    make_PHP_serialized_bytestream_from_array: function(arrName) {
      /* assumes array values have form {key:value} */
      var escapeDblQt = /"/;
      this.toString = function() { return 'make_PHP_serialized_bytestream_from_array'; }
      eval("var arr = " + arrName);
      if (!(typeof arr=='undefined')) {
        var str = '', val = '';
        var count = 0;
        for (count; count<arr.length; count++) {
          hash = arr[count].split(':');
          if ('0'===hash[0] || !isNaN(parseInt(hash[0]))) {
            str += 'i:' + parseInt(hash[0]) + ';';
          } else {
            str += 's:' + hash[0].length + ':"' + hash[0].replace(escapeDblQt, '\"') + '";';
          }
          if (!hash[1] || ''==hash[1]) {
            str += 'N;';
          } else {
            str += 's:' + hash[1].length + ':"' + hash[1].replace(escapeDblQt, '\"') + '";';
          }
        }
        str = 'a:' + count + ':{' + str + '}';
        return (str);
      } else {
        return (-1);
      }
    },

    make_PHP_serialized_array_keys: function(arrName, arrID) {
      /* assumes array values have form {key:value} */
      var escapeDblQt = /"/;
      this.toString = function() { return 'make_PHP_serialized_array_keys'; }
      eval("var arr = " + arrName);
      if (!(typeof arr=='undefined')) {
        var str = '', val = '';
        var count = 0;
        for (count; count<arr.length; count++) {
          hash = arr[count].split(':');
          if ('0'===hash[0] || !isNaN(parseInt(hash[0]))) {
            str += 'i:' + parseInt(hash[0]) + ';';
          } else {
            str += 's:' + hash[0].length + ':"' + hash[0].replace(escapeDblQt, '\"') + '";';
          }
          if (!hash[1] || ''==hash[1]) {
            str += 'N;';
          } else {
            str += 's:' + hash[1].length + ':"' + hash[1].replace(escapeExp, '\"') + '";';
          }
        }
        str = 'a:' + count + ':{' + str + '}';
        return (str);
      } else {
        return (-1);
      }
    },
    
    make_PHP_serialized_bytestream_from_data_object: function(objName) {
//alert('153: ' + objName);    
      var escapeDblQt = /"/;
      this.toString = function() { return 'make_PHP_serialized_bytestream_from_data_object'; }
      eval("var obj = " + objName);
      if (!(typeof obj=='undefined')) {
        var str = '', val = '';
        var count = 0;
        for (var f in obj) {
          str += 's:' + f.length + ':"' + f.replace(escapeDblQt, '\"') + '";';
          val = eval("obj."+f);
          if (!val || ''==val) {
            str += 'N;';
          } else {
            str += 's:' + val.length + ':"' + val.replace(escapeDblQt, '\"') + '";';
          }
          ++count;
        }
        str = 'a:' + count + ':{' + str + '}';
        return (str);
      } else {
        return (-1);
      }
    },
    
    getFormValues: function(form_id, is_standalone) {
      if (false === this.isValidUser) { return false; }
      this.toString = function() { return 'getFormValues'; }
      this.activeFormID = form_id;
      this.isStandalone = (1==is_standalone);
//alert('FORM ID = ' + this.activeFormID + '; IS STANDALONE IS ' + this.isStandalone.toString());      

      var f = document.getElementById(this.activeFormID);
//alert('FORM ID ' + this.activeFormID + ' IS A ' + typeof f + '; NUMBER OF ELEMENTS = ' + f.elements.length + '; IS VALID USER = ' + this.isValidUser);    
      if (!this.isStandalone) {
        if (f && f.elements) {
          formNames = "[";
          for (var n=0; n<f.elements.length; n++) {
            if ('' != f[n].name) {
//alert(f[n].nodeName + ' ' + f[n].name + ' = ' + f[n].value);
//            formNames += ("'" + n + "':'" + f[n].name + "',");
              formNames += ("'" + f[n].name + "',");
            } // if ''
          } // for
          formNames = formNames.substring(0,formNames.length-1) + "]";
//alert(formNames);
          serNames = this.make_PHP_serialized_bytestream_from_array(formNames);
//alert("GET FORM VALUES serNames = " + serNames);
          this.get_data(serNames);
        }
      } else {
        this.get_standalone_data(form_id);
//        formNames = "{";
//        for (var n=0; n<f.elements.length; n++) {
//          if ('' != f[n].name) {
//            formNames += ("'" + f[n].name + "':'',");          
//          } // if
//        } // for
//        formNames = "{'" + form_id + "':{" + formNames.substring(0,formNames.length-1) + "}}";
//alert('formNames OBJECT: \n' + formNames);
//        serNames = this.make_PHP_serialized_bytestream_from_data_object(formNames);
//         //serNames = "a:2{s" + form_id.length + ':"' + form_id + '";' + serNames + "}";
//alert('serNames: \n' + serNames + '\nLENGTH OF serNames = ' + serNames.length);
      } // if !this.isStandalone
    },
    
    saveFormValues: function(form, is_standalone) {
//alert('FORM ID = ' + form.id + '; IS STANDALONE = ' + is_standalone);    
      this.activeFormID = form.id;
      this.isStandalone = (typeof is_standalone!='undefined' && 1==is_standalone);
//alert('FORM ID = ' + this.activeFormID + '; IS STANDALONE = ' + this.isStandalone.toString());      
      formValues = "{";
      this.toString = function() { return 'saveFormValues'; }
      for (var n=0; n<form.elements.length; n++) {
        if ('' != form[n].name) {
          switch (form[n].type) {
            case 'text':
//alert('1: ' + form[n].nodeName + ' ' + form[n].name + ' = ' + form[n].value);
              if (''!=form[n].value && 'NaN'!=(form[n].value)) {
                formValues += ("'" + form[n].name + "':'" + form[n].value.prepare() + "',");
              } else {
                formValues += ("'" + form[n].name + "':'',");
              }
              break;
            case 'checkbox':
//alert('2: ' + form[n].nodeName + ' ' + form[n].name + ' has type ' + form[n].type + ' and value ' + form[n].value);        
              if (form[n].checked) {
                formValues += ("'" + form[n].name + "':'1',");
              } else {
                formValues += ("'" + form[n].name + "':'0',");
              }
              break;
            case 'select':
//alert('3: ' + form[n].nodeName + ' ' + form[n].name + ' has type ' + form[n].type + ' and value ' + form[n].options[form[n].selectedIndex].value);        
              if (form[n].selectedIndex) {
                formValues += ("'" + form[n].name + "': [" + form[n].options[form[n].selectedIndex] + ",'" + form[n].options[form[n].selectedIndex].value + "'],");
              } else {
                formValues += ("'" + form[n].name + "':[0,''],");
              }
              break;
            default:
              if (''!=form[n].value && 'NaN'!=(form[n].value)) {
//alert('1a: ' + form[n].nodeName + ' ' + form[n].name + ' has type ' + form[n].type + ' and value ' + form[n].value);        
                formValues += ("'" + form[n].name + "':'" + form[n].value.prepare() + "',");
              } else {
                formValues += ("'" + form[n].name + "':'',");
              }
          } // switch
        } // if
      } // for
      formValues = formValues.substring(0,formValues.length-1) + "}";
//alert('FORM FUNCTIONS LINE 203: FORM VALUES: ' + formValues);
      serValues = this.make_PHP_serialized_bytestream_from_data_object(formValues);
      if (this.isStandalone) {
        if ("a:1:{" != serValues.substring(0,5)) {
          serValues = "a:1:{s:" + this.activeFormID.length + ':"' + this.activeFormID + '";' + serValues + "}";
        }
      }
//alert('FORMFUNCTIONS LINE 202, SERVALUES = ' + serValues + '\nLENGTH OF serValues = ' + serValues.length);
      this.save_data(serValues);
    },
    
    saveSundryValues: function(form_id) {
      this.toString = function() { return 'saveSundryValues'; }
      var underscore = /_/g;
      var form = document.getElementById(form_id);
      var product = this.get_product();
      this.activeFormID = form_id;
      var qs = "";
//alert(form_id + ' HAS ' + form.elements.length + ' ELEMENTS');      
      for (var n=0; n<form.elements.length; n++) {
//alert('0: ' + form[n].nodeName + ' ' + form[n].name + ' = ' + form[n].value);
        if ('' != form[n].name) {
          switch (form[n].type) {
            case 'text':
//alert('1: ' + form[n].nodeName + ' ' + form[n].name + ' = ' + form[n].value);
              if (''!=form[n].value && 'NaN'!=form[n].value && 'MM'!=form[n].value && 'DD'!=form[n].value && 'YYYY'!=form[n].value) {
//alert('FIRST 5 = ' +  form[n].name.substring(0,5));             
                if ('birth' != form[n].name.substring(0,5) && 'username'!=form[n].name) {
                  qs += form[n].name + "=" + form[n].value.prepare() + "&";
                }
              } else {
                alert('Please enter a value for your ' + form[n].name.replace(underscore, ' '));
                form[n].focus();
                return false;
//                qs += form[n].name + "=" + form[n].value + "&";
              }
              break;
            case 'checkbox':
//alert('2: ' + form[n].nodeName + ' ' + form[n].name + ' has type ' + form[n].type + ' and value ' + form[n].value);        
              if (form[n].checked) {
                qs += form[n].name + "=1&";
              } else {
                qs += form[n].name + "=0&";
              }
              break;
            case 'select':
//alert('3: ' + form[n].nodeName + ' ' + form[n].name + ' has type ' + form[n].type + ' and value ' + form[n].options[form[n].selectedIndex].value);        
              if (form[n].selectedIndex) {
                qs += form[n].name + "=" + form[n].options[form[n].selectedIndex].value + "&"
              } else {
                qs += form[n].name + "=" + form[n].options[0].value + "&";
              }
              break;
            default:
              if (''!=form[n].value && 'NaN'!=(form[n].value)) {
                qs += form[n].name + "=" + form[n].value.prepare() + "&";
              } else {
                qs += form[n].name + "=" + form[n].value + "&";
              }
          } // switch
        } // if
      } // for
      qs += "birthdate=" + form.birth_month.value + "::" + form.birth_day.value + "::" + form.birth_year.value;
      var i = window.location.pathname.substr(1).indexOf("/"); // CH 20080731
      this.cuid = window.location.pathname.substr(1, i);       // CH 20080731
      var url = "/"+this.cuid+"/js/save_sundry_data.php?product="+product+"&"+qs;
//alert("SAVE SUNDRY VALUES 414: CUID = " + this.cuid + "\nURL = " + url);
//return false;
      this.xmlhttp = this.make_xmlhttp_client();
      // cross browser
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.saveSundryValues_response(); // NB: at this level 'this' refers to the immediate, anonymous function, not to the class
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }
    },

    saveSundryValues_response: function() {
      if (4==this.xmlhttp.readyState && 200==this.xmlhttp.status) {
        alert(this.xmlhttp.responseText);
      }
    },

    hideDeleted: function() {
      deleted_cats = document.getElementById('deleted_cats');
      hideArr = deleted_cats.value.split('del');
      for (var i=1; i<hideArr.length; i++) {
        if ('' != hideArr[i]) {
          var delImg = document.getElementById('del'+hideArr[i]);
          if (delImg) {
            document.getElementById('retire_checklist').deleted_cats.value += "::del" + +hideArr[i];
            deletedCats.push(delImg);
            delImg.parentNode.parentNode.style.display = 'none';
          }
        }
      }
    },

    XsaveFormValues: function(f) {
      formValues = "{";
      this.toString = function() { return 'saveFormValues'; }
      for (var n=0; n<form.elements.length; n++) {
        if ('' != f[n].name) {
          switch (f[n].type) {
            case 'text':
//        alert(f[n].nodeName + ' ' + f[n].name + ' = ' + f[n].value);
              if (''!=f[n].value && 'NaN'!=(f[n].value)) { //
                formValues += ("'" + f[n].name + "':'" + f[n].value.prepare() + "',");
              } else {
                formValues += ("'" + f[n].name + "':'',");
              }
              break;
          
          
          } // switch
        } // if
      } // for
      formValues = formValues.substring(0,formValues.length-1) + "}";
//alert(formValues);
      serValues = this.make_PHP_serialized_bytestream_from_data_object(formValues);
//alert('LENGTH OF serValues = ' + serValues.length);
      this.save_data(serValues);
    },

    fill_firstname: function(id, conditionalText, placement, alternativeText) {
//alert('FORM FUNCTION 256: CONDITIONAL TEXT: |' + conditionalText + "| placement: " + placement);
      eval("var target = document.getElementById('" + id + "')");
//alert ('TARGET IS A ' + typeof target + ' FIRST NAME = ' + this.userFirstName);
      if (0 < this.userFirstName.length) {
        if (0 < conditionalText.length) {
          switch (placement) {
            case 'mid':
              var textparts = conditionalText.split("::");
              target.innerHTML = textparts[0] + this.userFirstName + textparts[1];
              break;
            case 'pre':
              target.innerHTML = conditionalText + this.userFirstName;
              break;
            case 'post':
              target.innerHTML = this.userFirstName + conditionalText;
              break;
            default:
              target.innerHTML = this.userFirstName;
          } //switch
        } else {
          target.innerHTML = this.userFirstName;
        }
      } else {
        target.innerHTML = alternativeText;
      }
    },

    fill_form: function() {
      var _skips = new Array();
//alert('IN FILL FORM. ACTIVE FORM ID = ' + this.activeFormID);
      if ('undefined' != typeof this.activeFormID) {
        f = document.getElementById(this.activeFormID);
        with (f) {
          var j = 0;
          for (var n in fieldData) {
            eval("var thisfield = f.elements['" + n + "'];");
            //if ('INPUT' == thisfield.nodeName) {
//alert('IN FILL FORM. NODE NAME = ' + thisfield.nodeName + '; TYPE OF thisfield = ' + thisfield.type + '; VALUE = ' + fieldData[n]);    
              switch (thisfield.type) {
                case "text":
                  eval("thisfield.value = '" + fieldData[n] + "';");
                  break;
                case "checkbox":
//if (10>j) alert('IN FILL FORM. FIELD DATA = ' + fieldData[n] + '; NODE NAME = ' + thisfield.nodeName + '; TYPE OF thisfield = ' + thisfield.type);    
                  eval("thisfield.checked = (1==" + fieldData[n] + ");");
                  break;
                case "hidden":
//alert('IN FILL FORM 378. FIELD DATA[N] = ' + fieldData[n]);    
                  arr = fieldData[n].split('del');
                  arr2 = new Array();
                  str = '';
                  for (var i=0; i<arr.length; i++) {
                    if ('' != arr[i]) {
                      if (typeof arr2[arr[i]] == 'undefined') {
                        str += '::del' + arr[i];
                      }
                      arr2[arr[i]] = 1;
                    }
                  }
//alert('STR = ' + str + ' AND THISFIELD NAME = ' + thisfield.name);                  
                  thisfield.value += str;
                  break;
                case "radio":
                  _new_radio = true;
                  for (var j=0; j<_skips.length; j++) {
                    if (n == _skips[j]) {
                      _new_radio = false;
                      break;
                    }
                  }
                  if (_new_radio) {
                    for (var j=0; j<thisfield.length; j++) {
                      if (fiendData[n] == j) {
                        thisfield[j].checked = true;
                      } else {
                        thisfield[j].checked = false;
                      }
                    }
                    _skips.push[n]
                  }
                  break;
              } // switch
            //} else if ('select' == thisfield.nodeName) {
              // to do -- use selectedIndex or match value?
            //}
//if ('c' != thisfield.name.substring(0,1)) alert(thisfield.name + ' VALUE = ' + thisfield.value);
            ++j;
          } // for
        } // with
      } // if
//alert('IN FILL FORM LINE 345. WINDOW LOADED = ' + window.loaded);      
      if (window.loaded) {
        try {
          makeDeleted();
          showDeleted();
        } catch(err) {
         // do nothing
        }
      }
    },

    get_standalone_data: function(id) {
      this.toString = function() { return 'get_standalone_data'; }
//alert('IN GET STANDALONE DATA.');    
      var product = this.get_product();
      if (''==this.userName) { this.userName = document.getElementById('log_username').value.trimEnds(); }
      var url = "/js_shared/get_user_data.php?product="+product+"&username="+this.userName+"&standalone=1&form_name=" + this.activeFormID;
//alert('IN GET STANDALONE DATA. URL = ' + url);
//document.writeln('IN GET STANDALONE DATA. URL = ' + url);   
      this.xmlhttp = null;
      try { // IE
        this.xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
      } catch (err) {
        try {
          this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (err) {
          this.xmlhttp = null;
        }
      }
      // FF
      if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
        this.xmlhttp = new XMLHttpRequest();
      }
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.get_data_response();
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }    
    
    },
    
    get_data: function(fields) {
      this.toString = function() { return 'get_data'; }
//alert('IN GET DATA. LENGTH OF serNames = ' + fields.length + "\n" + fields);    
      var product = this.get_product();
      if (''==this.userName) { this.userName = document.getElementById('log_username').value.trimEnds(); }
      var url = "/js_shared/get_user_data.php?product="+product+"&username="+this.userName;
      if (this.activeFormID) { url += "&form_name=" + this.activeFormID; }
      url += "&val="+fields;
//alert('IN GET DATA. URL = ' + url);
//document.writeln('IN GET DATA. URL = ' + url);   
      this.xmlhttp = null;
      try { // IE
        this.xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
      } catch (err) {
        try {
          this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (err) {
          this.xmlhttp = null;
        }
      }
      // FF
      if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
        this.xmlhttp = new XMLHttpRequest();
      }
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.get_data_response();
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }
    },

    get_data_response: function() {
      var _response;
      if (4==this.xmlhttp.readyState && 200==this.xmlhttp.status) {
        _response = new String(this.xmlhttp.responseText);
//alert("441 GET DATA RESPONSE TEXT: |" + _response + '|');
        _start = _response.search(/\{/);
        if (-1 < _start) {
          _response = _response.substr(_start);
        }
//alert("434 GET DATA RESPONSE TEXT: |" + _response + '|');
        _first_char = _response.substring(0,1);
        if (2 > _response.length) { 
          return; 
//        } else if ('{'!=_first_char && 512>_response.length) {
//alert('IN GET DATA RESPONSE 282. TEXT = |'+_response+'|');
        } else {
          eval("fieldData = " + _response + ";");
//alert('IN GET DATA RESPONSE 442. TYPE OF fieldData = ' + (typeof fieldData));    
          this.fill_form();
//alert('IN GET DATA RESPONSE 444. ACTIVE FORM ID = ' + this.activeFormID);    
//          if ('retire_checklist'==this.activeFormID) {
//            this.hideDeleted();
//          }
        }
      } // if 4
    },

    save_data: function(str) {
      this.toString = function() { return 'save_data'; }
//alert('IN SAVE DATA. LENGTH OF serValues = ' + str.length + "\n" + str);    
      var product = this.get_product();
      var url = "/js_shared/save_user_data.php?product="+product;
      if (this.activeFormID) { url += "&form_name=" + this.activeFormID; }
//alert('IN SAVE DATA. IS STANDALONE = ' + this.isStandalone.toString());
      if (this.isStandalone) { url += "&standalone=1"; }
      url += "&val="+str;
      this.xmlhttp = null;
      try { // IE
        this.xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
      } catch (err) {
        try {
          this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (err) {
          this.xmlhttp = null;
        }
      }
      // FF
      if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
        this.xmlhttp = new XMLHttpRequest();
      }
      // cross browser
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.save_data_response(); // NB: at this level 'this' refers to the immediate, anonymous function, not to the class
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }
    },

    save_data_response: function() {
      if (4==this.xmlhttp.readyState && 200==this.xmlhttp.status) {
        alert(this.xmlhttp.responseText);
      }
    },
    
    add_to_favorites: function(title) {
      this.toString = function() { return 'add_to_favorites'; }
      var product = this.get_product();
      var url = "/include/add_to_favorites.php?page="+window.location.href.substr(window.location.protocol.length+"//".length+window.location.host.length)+"&title="+encodeURIComponent(title)+"&product="+product;
//alert('URL: ' + url);
      this.xmlhttp = this.make_xmlhttp_client();
      // cross browser
      if (this.xmlhttp) {
        this.xmlhttp.onreadystatechange = function() {
          formFunctions.save_data_response(); // NB: at this level 'this' refers to the immediate, anonymous function, not to the class
        }
        try {
          this.xmlhttp.open("GET",url,true);
        } catch(err) {
          alert('ERROR: ' + err);
        }
        if (window.ActiveXObject) {
          this.xmlhttp.send();
        } else if (window.XMLHttpRequest) {
          this.xmlhttp.send(null);
        }
      }
    },
    
    add_to_favorites_response: function() {
      if (4==this.xmlhttp.readyState && 200==this.xmlhttp.status) {
        alert(this.xmlhttp.responseText);
      }
    }    
  };
