//------------------------------------------------------------------------------------------
function igetElement(id)
//get element by id or name
//fields are posted to server by name. IE get by id works on name if no id for sone elements [but not, e.g td]... but Mozilla is by id only. Mozilla can get some element types by name but not all...
//one way round is to give all elements both names and ids. This is an alternative
{
var o = document.getElementById(id);    //quickest way if it works

if (o) return o;                    //got it - either it had an id or IE found it

//if  (navigator.appName=="Microsoft Internet Explorer") return o;   //if it was IE and not found, id/name doesn't exist - might be a td etc

o = document.getElementsByName(id)[0];    //try looking by name
if (o) return o;

var all = document.getElementsByTagName('*');   //last resort - go through all elements looking for matching name - should get e.g trs and tds
var imax = all.length;
 for (var i = 0;i<imax;i++) {
   if (all[i].name == id) return all[i];
   }
return o;           //not found
}

//------------------------------------------------------------------------------------------
function csvescape(s)
//csv encode a string
{
if (/"/.test(s)) {           //if string contains " would muck up csv, so
  return '"' + s.replace( /"/g,'""') + '"';       //put quotes round it, doubling any quotes already there
  }

//next line means take the regular expression "," and see if it's in s
if (/,/.test(s)) {           //if string contains comma(s) would muck up csv, so
  return '"' + s.replace( /"/g,'""') + '"';       //put quotes round it, doubling any quotes already there
  }
else return s;
}
//------------------------------------------------------------------------------------------
function uncsvescape(s)
//un csv encode a string
{
if (s.charAt(0) != '"') return s;  //didn't start with a quote so no unescaping needed
s = s.substr(1,s.length-2);        //remove leading and ending dbl quotes

return s.replace( /""/g,'"');       //replace any pairs of double quotes with single characters
}
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
function splitcsv(s)
//split a csv string into an array of fields - a string with a comma is double quoted, in quoted strings real double quotes are doubled
//note this recognises a quoted field only when it start witha double quote - any white space first and it's treated as a non quoted field. all other fileds pass through
{
var i;
var imax;
var iend;
var c;
var c2;
var sres='';
var ifld = 0;
var ares = new Array();

imax = s.length;
for (i=0;i<imax;i++) {
  c = s.charAt(i);
  if (c=='"') {      //start of a quoted field - handle any doubled double quotes inside, ignore commas inside
    for (i++;i<imax;i++) {      //process the quoted field
      c = s.charAt(i);
      if (c=='"') {    //should be either a doubled quote or end of the field
        i++;
        if (i>=imax) break;     //shouldn't happen - off end without terminator
        c2 = s.charAt(i);
        if (c2=='"') {   //doubled quote
          sres+=c2;
          }
        else {
          break;
          }
        }
      else {
        sres+=c;         //normal character - add to the field
        }
      }
    }
  else {             //start of a non quoted field - just pass it through
    iend = s.indexOf(",", i);     //find the closing ,
    if (iend == -1) {             //no closing ,
      iend = s.length;
      }
    sres = s.substring(i, iend);
    i = iend;
    }
                        //end of field
  ares[ifld] = sres;//save this field and update ready for next field
  ifld++;
  sres='';
  }

return ares;
}
//------------------------------------------------------------------------------------------
function mlogout(surl)  //called on logout - clear cookie on PC
{

saveCookie ('uc', '');
if (surl && surl != '') document.location.href=surl;   //and move on to logged out page if any

else document.location.href=document.location.href;
}
//------------------------------------------------------------------------------------------
function saveCookie (name, value)  //save cookie with long expiry date
{
return setCookie (name, value, 9999);
}
//------------------------------------------------------------------------------------------
function setCookie (name, value, lifespan, access_path) {

  var cookietext = name + "=" + ckescape(value);
    if (lifespan != null) {
      var today=new Date();
      var expiredate = new Date();
      expiredate.setTime(today.getTime() + 1000*60*60*24*lifespan);
      cookietext += "; expires=" + expiredate.toGMTString();
    }
    if (access_path != null) {
      cookietext += "; PATH="+access_path;
    }
   document.cookie = cookietext;
   return null;
}
//------------------------------------------------------------------------------------------
function setDatedCookie(name, value, expire, access_path) {
    var cookietext = name + "=" + ckescape(value);
      + ((expire == null) ? "" : ("; expires=" + expire.toGMTString()));
     if (access_path != null) {
      cookietext += "; PATH="+access_path;
     }
   document.cookie = cookietext;
   return null;
}
//------------------------------------------------------------------------------------------
function getCookie(name) {
  var offset;
  var end;
  var search = name + "=";
  var CookieString = document.cookie;
  var result = null;

  if (CookieString.length > 0) {
    offset = CookieString.indexOf(search);
    if (offset != -1) {
      offset += search.length;
      end = CookieString.indexOf(";", offset);
      if (end == -1)
        end = CookieString.length;
      result = unckescape(CookieString.substring(offset, end));
//      result = CookieString.substring(offset, end);

      }
    }
   return result;
}
//------------------------------------------------------------------------------------------
function deleteCookie(Name, Path) {
  setCookie(Name,"Deleted", -1, Path);
}
//------------------------------------------------------------------------------------------
function ckescape(s)
//escape a string suitable to go in a cookie - note can't use built in escape?
{
//  return  s.replace( /¬/g,'¬¬').replace( /;/g,'¬s').replace(/"/g,'¬q');       //double any ¬s already there, then replace any ; with ¬s
  return  s.replace( /¬/g,'¬¬').replace( /;/g,'¬s');       //double any ¬s already there, then replace any ; with ¬s - don't need to escpae double quotes
}
//------------------------------------------------------------------------------------------
function unckescape(s)
//unescape a string from a cookie
{
var i;
var imax;
var c;
var sres='';

imax = s.length;
for (i=0;i<imax;i++) {
  c = s.charAt(i);
  if (c=='¬') {      //possible digraph
    i++;
    if (i >= imax) break;       //shouldn't happen
    switch (s.charAt(i)){
    case '¬':      //dbl escape char - means just esc char
      sres += c;
      break;
    case 'q':      //dbl quote
      sres += '"';
      break;
    case 's':      //semi colon
      sres += ';';
      break;
    default:       //shouldn't happen - unknown digraph - just pass through
      sres += c + s.charAt(i);
      }
    }
  else {
    sres += c;    //other chars just pass through
    }
  }
return sres;
}
//------------------------------------------------------------------------------------------
function m_setvisibility(objnam,vis)
{
var o = igetElement(objnam);

if (!o) return;                                  //none found
if (vis) {
  o.style.display='inline';
  }
else {
  o.style.display='none';
  }
}
//-----------------------------------------------------------------------------------------------
function m_mousehelp(evt) //display help for the area entered by the mouse
{

  if(evt==null) evt=window.event;									//what element are we on?
  var o = (evt.target) ? evt.target : evt.srcElement;

  if (!o) {
    m_sethelp('');
    return;
    }

    m_sethelp(o.name);
}
//-----------------------------------------------------------------------------------------------
function m_mouseout(mynam)
//for help tips
{
return;

var o = igetElement('helppane');
o.innerHTML = "";
}
//-----------------------------------------------------------------------------------------------
function m_sethelp(mynam)
//for help tips
{
var o = igetElement('helppane');
o.innerHTML = m_gethelp(mynam);
//o.innerHTML = m_gethelp(mynam) + '<br><br><br><b>' + mynam + '</b>';  //diagnostic - add field name
}
//------------------------------------------------------------------------------------------------------------------
function FormatMyNumber(fmtnum, numdec)
// like vbscript equivalent but returns zeros for zero, not blank
{
  var s;
  var s0;

//  if fmtnum = 0 then      vbscript version makes 0 space
//    FormatMyNumber = "&nbsp;"
//  elseif numdec = 0 then

try {                   //catch problem if fmtnum isn't a number
  if (numdec == 0) {
    return fmtnum.toFixed(0);
    }
  else {

//the following is a fix for an error formatting in JS for values 0.05 to 0.094 to 1 dp (and similalry for negative nums or different dps)

    var xx = Math.pow(10,-numdec);
    if (fmtnum < xx) {    //may be in an area where MS JS gets it wrong, e.g. 0.05 to 0.099 where numdec = 1 formatted as 0
      if (fmtnum >= 0.5 * xx) {
        fmtnum += 0.5 * xx;       //ensure formats OK
        }
      else if ((fmtnum > -xx) && (fmtnum <= -0.5 * xx)) {
        fmtnum -= 0.5 * xx;       //ensure formats OK
        }
      }

 // MW amend to strip trailing zeroes after decimal point - if they are all zeroes after dec point only
    s  =  fmtnum.toFixed(numdec);
    s0 =  fmtnum.toFixed(0);
    if (parseFloat(s) == parseFloat(s0)) {        //if there are trailing zeroes
      return s0;
      }
    else {
      return s;
      }
    }
  } catch (e) {return '0'; }

}
//-----------------------------------------------------------------------------------------------
function mcheckphone(s)
{
if ((s.length) < 10) return false;

  if (/[^0-9 ]/g.test(s)) {      //if contains anything except digits and spaces
    return false;
    }

return true;
}
//-----------------------------------------------------------------------------------------------
function checkemail(s)
{

  var re = new RegExp('^[^@<: ]+@[^@<: ]+[^@<: ]+\\.[^@<: ]+[^@<: ]+$','i');   //case independent regular expression, elt11@elt2.elt3 - elts can also contain dots
  if ( !re.test(s)) {          //doesn't match
    return false;
    }

return true;
}
//-----------------------------------------------------------------------------------------------
function m_submit()
{
if (!m_validate()) return false;           //failed validation

m_save();            //save fields to cookie for later

return true;
}
//-----------------------------------------------------------------------------------------------
function m_save_ex(flds, cookiename)
{
var i;
var s = '';
var mysep = '';
var o;

for (i=0;i<flds.length;i++) {  //save all known fields to cookie  - NOTE if format changes, use another cookie arg - keep this list invariant - or add cookiever

//  if (!igetElement(flds[i])) alert('no field: ' + flds[i]);
//  s += mysep + csvescape(igetElement(flds[i]).value);  //ensure safe as csv
//  if (!igetElement(flds[i])) alert('no field: ' + flds[i]);
  o = igetElement(flds[i]);
  if (o) {
    if (o.type == 'checkbox') {
      if (o.checked) {
        myval = '1';
        }
      else {
        myval = '0';
        }
      }
    else {
      myval = o.value;
      }
    }
  else {
    myval = '';       //field not present on form = would prefer to preserve value already present in cookie if any
    }
  s += mysep + csvescape(myval);  //ensure safe as csv
  mysep = ',';                   //separator after first field etc
  }
saveCookie(cookiename,s);
}
//-----------------------------------------------------------------------------------------------
function m_read_ex(flds,cookiename)
{
var cflds;
s = getCookie(cookiename);
var i,j;
var o;
var myval;
var objs;

try {                     //s may be null
  cflds = splitcsv(s);       //split our cookie back to fields

  for (i=0;i<cflds.length;i++) {  //restore all fields from cookie
    if (cflds[i]) {
      myval = uncsvescape(cflds[i]);
      o = igetElement(flds[i]);
      if (o) {                      //if corresponding field present on this form
        if (o.type == 'checkbox') {
          o.checked = (myval == '1');
          }
        else if (o.type == 'radio') {
          objs = libCtlArray(flds[i]);

          for (j=0;j<objs.length;j++) {
            if (objs[j].value==myval) {
              objs[j].checked=true;
              break;
              }
            }
          }
        else {
          o.value = myval;
          }
        }
      }
    }
  } catch (e) { };

}
//------------------------------------------------------------------------------------------------------------------
function libCtlArray(nam) {
var c = document.forms[0][nam];
if ((c == null) || (typeof(c) == 'undefined'))
  return new Array();
else if (c.length > 0)
  return c;
else
  return new Array(c);
}
//------------------------------------------------------------------------------------------------------------------
function igetRadioValue(nam) //get the value assigned to the checked member of a ste of radio buttons
{
var i;
var objs = libCtlArray(nam);

for (i=0;i<objs.length;i++) {
  if (objs[i].checked) {
    return objs[i].value;
    }
  }
}
//------------------------------------------------------------------------------------------------------------------
function isChecked(nam)  //return true if checkbox exists and is checked
{
try {
  if (igetElement(nam).checked) return true;
   }  catch (e) {;}

return false;
}
//------------------------------------------------------------------------------------------------------------------
function Trim(s)     //return string less leading and training space if any
{
if (s.substr(0,1)==' ') s=s.substr(1);      //trim any leading space

var ilen = s.length -1;
if (s.substr(ilen,1) == ' ') s=s.substr(0,ilen);   //trim any trailing space

return s;
}
//------------------------------------------------------------------------------------------------------------------
function CapitaliseNameField(nam)
{
var o = igetElement(nam);

if (!o) return;
o.value = CapitaliseName(o.value);
}
//------------------------------------------------------------------------------------------------------------------
function CapitaliseName(s)
{
var names;
var i;

s = s.replace(/ +/g,' ');  //first collapse any multiple spaces

s = Trim(s);

names = s.split(' ');

for(i = 0; i < names.length; i++) {
   if (names[i].length > 1) {
     names[i] = CapitaliseSubName(names[i]);
     }
	else {
    names[i] = names[i].toUpperCase();      //single letter
    }
	}

return names.join(' ');
}
//----------------------------------------------------
function CapitaliseSubName(s)
//capitalise a sub part of a name that has been parsed for spaces, may have a hyphen
{
names = s.split('-');          //split at any hyphens
for(i = 0; i < names.length; i++) {
  if (names[i].length >= 1) {
    if (notSpecialCaseName(names[i])) {      //leave special cases alone, hope user capitalised OK
  	   names[i] = names[i].toLowerCase();
  	   letters = names[i].split('');
       letters[0] = letters[0].toUpperCase();
  	   names[i] = letters.join('');
      }
    }
  }

return names.join('-');
}
//----------------------------------------------------
var mySpecialCasePrefices=new Array("Mc","Mac","O'"); //prefices followed by a capital
var mySpecialCaseNames=new Array("de","van","du");    //name parts not to start capital

function notSpecialCaseName(s)
{
var i;
var imax;

imax= mySpecialCasePrefices.length;
for (i=0;i<imax;i++) {
  if (s.substr(0,mySpecialCasePrefices[i].length)== mySpecialCasePrefices[i]) return false;   //it is a special case
  }

imax= mySpecialCaseNames.length;                   //these would need to match exactly
for (i=0;i<imax;i++) {
  if (s== mySpecialCaseNames[i]) return false;   //it is a special case
  }

return true;                       //not a special case
}
//----------------------------------------------------



