// SCRIPT MAIL LIBRARY   ECMAScript v3.0   (c) 2007 Codesmiths codesmiths.com.au - all rights reserved
//  
// a Global object CSS07 is assumed declared,  the name CSS07  may be made unique for deployment 
// this relies on CSS07 being populated with CSS07.kpl
try
{

// ===========================================================================
// NAMESPACE MANAGEMENT - ONLY ONE GLOBAL IDENTIFIER RESERVED ('CSS07')
  if (!CSS07.kpl) { window.status = 'CSM-LIB: CSS07.kpl not loaded]'; throw new Error(window.status); }

  if (!CSS07.mfm) { CSS07.mfm = {USAGE:'codesmiths.com.au ecmascript mail form management lib'}; } 

// A form processor which will alter elements based on a querystring after processing
// Part of a generic pattern to allow smart processing of any html form
// formId which Form
// sendId postback button
// postTo URI to postback to
// headID, footID, where to display response info
// txtOK, txtFail, test to display if we get an OK or not
// classes to style reponse text classOK, classFai

CSS07.mfm.FormManager = function (formId, sendId, postTo, headID, footID, txtOK, txtFail, classOK, classFail) 
        {
          try
          {
            if (!(this instanceof CSS07.mfm.FormManager ))               { return null; }          // constructor was CALLed as a function
            
            this.send = document.getElementById(sendId);
            if (!this.send)                         { this.form = null; return null; }   
            
            if (document.location.search.length === 0) {
              
              this.form = document.getElementById(formId);
              if (!this.form)                                           { return null; }          

              CSS07.kpl.Encapsulator.call(this);                   // 'inherit'   Encapsulator's features
            
              this.unload = this.bindEvent(window, this.bind(this,'destroy'), 'unload');            // function ref (evtHdlr) stored for unbinding
              // if the page being loaded has no search string, the form is active:
              // set up the submit button for postback
              this.server = postTo;  
              this.event = 'click';
              this.submit = this.bindEvent(this.send, this.bind(this,this.postback), this.event);   // function ref (evtHdlr) stored for unbinding
              this.posted = false;
              
            } else {
            
              // this is a post-submit instance 
              // the next 2 param names are reserved and should not be used as ID's in the html
              var param1  = 'result';
              var param2  = 'info';
              var attval  = 'value';
              var classv  = 'class';
              var okVal   = 'OK';
              var eqchar  = '=';
              var sepchar = '&';
              var fields  = document.location.search.split(sepchar);
              var error   = false;
              var pair;
              
              // first value is status of result, use indexOf to skip the leading "?" 
              if (fields[0].indexOf(param1) > -1) {
                pair = fields[0].split(eqchar);
                var head = document.getElementById(headID);
                if (head) {
                  if (pair[1] == okVal){
                    head.innerHTML = txtOK;
                    head.className = (error ? classFail : classOK);
                  } else {
                    error = true;
                    head.innerHTML = txtFail;
                    head.className = (error ? classFail : classOK);
                  }
                }
              } else { return ; }
              this.posted = true;
              // iterate through the reply fields and put back the values.
              for (ii=1; ii<fields.length; ii++) {
                pair = fields[ii].split(eqchar);
                elt = document.getElementById(pair[0]);
                if (elt) {
                  if (elt.type == 'textarea') {
                    elt.innerHTML = decodeURIComponent(pair[1]);
                  } else {
                    elt.setAttribute(attval,decodeURIComponent(pair[1]));
                  }
                } else {
                  if (pair[0] == param2 && pair[1].length > 0) {
                    var foot = document.getElementById(footID);
                    if (foot) {
                      foot.innerHTML = decodeURIComponent(pair[1]);
                      foot.setAttribute(classv, (error ? classFail : classOK));
                    }
                  }
                }
              }

              this.allow_submit(false);
            }
          }
          catch(e){this.destroy();}
        };

CSS07.mfm.FormManager.prototype.destroy = function ()
        {
          try
          {
            if (this.submit)
            {
              this.unbindEvent(this.send, this.submit, this.event);
              this.submit = null;
              this.event = null;
            }
            this.unbindEvent(window, this.unload, 'unload');
            this.send = null;
            this.form = null;
          }
          catch(e){} 
        };
 
CSS07.mfm.FormManager.prototype.allow_submit = function (allow)
        {
          try
          { 
            this.send.disabled = (this.posted || !allow) ;
          }
          catch(e){} 
        };

CSS07.mfm.FormManager.prototype.postback = function (evt)
        {
          try
          { 
            if (!!this.server) {
              this.form.action = this.server;
            }
            this.form.method = 'post';
            this.form.enctype= 'multipart/form-data';
            // decorate the input fields with name attributes for aspx
            var controls = new Array();
            CSS07.csm.selectDescendants(this.form, 'INPUT', controls);
            CSS07.csm.selectDescendants(this.form, 'TEXTAREA', controls);
            for (var ii = 0; ii < controls.length; ii++){
              var ctrl= controls[ii];
              var attr = ctrl.getAttribute('id');
              if (attr) { ctrl.setAttribute('name', attr); }
            }
            this.allow_submit(false);
            this.form.submit();
          }
          catch(e){} 
        };

// A very basic form validator which manages leds on essential fields
// it could add the leds if they are not present??
// An Optional form manager object allows enabling submit when all essentials have minimum length
CSS07.mfm.BasicValidator = function (essentials, min_length, led_suffix, objForm) 
        {
          try
          {
            if (!(this instanceof CSS07.mfm.BasicValidator ))             { return null; }        // constructor was CALLed as a function
            
            if (objForm) {                                                                       // a form object is optional
              if (!(objForm instanceof CSS07.mfm.FormManager ))           { return null; }        // constructor dependency missing
              this.manager = objForm;
            }  else { this.manager = null; }
            
            var c = ',';                                        // special characters
            this.minLength = min_length > 2 ? min_length : 2; 
            this.ledSuffix = led_suffix     ? led_suffix : '_led';
            
            
            var fields = essentials.split(',');

            this.eventElmts = new Array;                        // elements with associated click events
            this.eventFuncs = new Array;
            this.eventTypes = new Array;                        // just change for now
 
            CSS07.kpl.Encapsulator.call(this);                   // 'inherit'   Encapsulator's features
            var ii = 0;                                         // index for mapped events
            for(var jj = 0; jj<fields.length; jj++) {
              // scan for user supplied duplicate strings's
              var curr_name = fields[jj];
              for(var kk = 0; kk < jj; kk++) {
                if (fields[kk] == curr_name) { break; }
              }  
              if (kk < jj || curr_name.length === 0) { break; }
              
              var eltID =  curr_name; 
              var elt = window.document.getElementById(eltID);              

              if(elt) {
                this.eventElmts[ii] = elt;
                this.eventFuncs[ii] = this.bind(this,this.change);  // the function refs must be stored for unbinding
                this.eventTypes[ii] = 'blur';
                this.bindEvent(this.eventElmts[ii], this.eventFuncs[ii], this.eventTypes[ii]);  // return ignored as we already saved the fn
                ii++;  
                this.led_check(elt);                               // set initial state
              }
            }

            this.unload = this.bindEvent(window, this.bind(this,'destroy'), 'unload');            // function ref (evtHdlr) stored for unbinding
            if (this.manager) { 
              this.score = ii;
              var count = this.count_essentials();
              this.manager.allow_submit(count >= this.score); 
            }
          }
          catch(e){this.destroy();}
        };

CSS07.mfm.BasicValidator.prototype.destroy = function ()
        {
          try
          {
            for(var ii = 0; ii<this.eventElmts.length; ii++) {
              if (this.eventElmts[ii])
              {
                this.unbindEvent(this.eventElmts[ii], this.eventFuncs[ii], this.eventTypes[ii]);
                this.eventElmts[ii] = null;
                this.eventFuncs[ii] = null;
                this.eventTypes[ii] = null;
              }
            }
            this.unbindEvent(window, this.unload, 'unload');
            this.manager = null;
          }
          catch(e){} 
        };
        
CSS07.mfm.BasicValidator.prototype.count_essentials = function ()                      // for submit enable 
        {
          try
            {
              var count = 0;
              for(var ii = 0; ii<this.eventElmts.length; ii++) {  
                count += this.char_check(this.eventElmts[ii]);
              }
              return count;
          }
          catch(e){} 
        };
            
CSS07.mfm.BasicValidator.prototype.change = function (evt)
        {
          try
          { 
            var elt = evt.target || evt.srcElement;
            this.led_check(elt);
            if (this.manager) { 
              var count = this.count_essentials();
              this.manager.allow_submit(count >= this.score); 
            }
          }
          catch(e){} 
        };
        
CSS07.mfm.BasicValidator.prototype.char_check = function (elt)
        {
          try
          { 
            var check = (elt.value.length > this.minLength);
            return (check ? 1 : 0);
          }
          catch(e){ return 0;} 
        };
        
CSS07.mfm.BasicValidator.prototype.led_check = function (elt)
        {
          try
          { 
            this.set_leds(elt, this.char_check(elt)); 
          }
          catch(e){ return 0;} 
        };

CSS07.mfm.BasicValidator.prototype.set_leds= function (elt, valid)
        {
          try
          {
            var spanID  = elt.id + this.ledSuffix;             // the leds are beside the textbox with related IDs
            var spanElt = document.getElementById(spanID);
            var img00 = CSS07.csm.selectDescendant (spanElt, 'img');
            var imgOK = CSS07.csm.selectDescendant (spanElt, '.valid'); 
            var show = 'inline';
            var hide = 'none';
            if (valid) {
              img00.style.display = hide;
              imgOK.style.display = show;
            }else{
              img00.style.display = show;
              imgOK.style.display = hide;
            }
          }
          catch(e){} 
        };
        
//                                                                                  // END: BasicValidator 
//  Utility possibilities 
//  use a validation score?        
CSS07.mfm.isContactable = function () 
        {
          var score=0; 
          var oForm = document.getElementById("contactus");
          if (isValid(oForm.fromName, "any")) {
            score = 1;
          }
          if (isValid(oForm.phone_bh, "phone")) {
            score |= 6;
         }
          if (isValid(oForm.phone_ah, "phone")) {
            score |= 6;
         }
          if (isValid(oForm.address, "any")) {
            score |= 2;
          }
          if (isValid(oForm.postcode, "postcode")) {
            score |= 4;
          }
          if (isValid(oForm.email, "email")) {
            score |= 6;
          }
          // The other fields are validated but do not contribute to score 
          if (isValid(oForm.suburb, "geographic")) {
            score |= 0;
          }
          if (isValid(oForm.state, "geographic")) {
            score |= 0;
          }
          if (isValid(oForm.country, "geographic")) {
            score |= 0;
          }
          return (score == 7);
        };
CSS07.mfm.isValid  = function (/* text Box */objVal, strType) 
    {
      var regExpPhone = /[^\d +()]/; 
      var regExpPostC = /[^a-z\d ]/i;
      var regExpGeogr = /[^a-z \-']/i;
      var regExpEmail = /^\w(\.?\w)*@\w(\.?[-\w])*\.([a-z]{3}(\.[a-z]{2})?|[a-z]{2}(\.[a-z]{2})?)$/i;
      var illegal = false;
      var strVal = objVal.value;
      switch (strType) {
        case "email":
          illegal = !regExpEmail.test(strVal) || (strVal.length < 4);
          break;
        case "phone":
          illegal = regExpPhone.test(strVal) || (strVal.length < 8);
          break;
        case "geographic":
          illegal = regExpGeogr.test(strVal) || (strVal.length < 2);
          break;
        case "postcode":
          illegal = regExpPostC.test(strVal) || (strVal.length < 4);
          break;
        case "any":
          illegal = (strVal.length === 0);
          break;
        default:
          illegal = (strVal.length === 0);
      }
      objVal.style.background = illegal ? "white" : "#E0FFE0"; /* pale green */
      return (!illegal);
    };
}
catch(e){} 

