// JavaScript Document
<!--
// Array to hold the permitted card characteristics
var cards = new Array();

// Define the cards we support. You may add addtional card types.

//  Name:      As in the selection box of the form - 
//  Length:    List of possible valid lengths of the card number for the card
//  prefixes:  List of possible prefixes for the card
//  checkdigit Boolean to say whether there is a check digit

cards [0] = {name: "Visa", 
		   length: "13,16", 
		   prefixes: "4",
		   checkdigit: true};
cards [1] = {name: "MasterCard", 
		   length: "16", 
		   prefixes: "51,52,53,54,55",
		   checkdigit: true};
cards [2] = {name: "DinersClub", 
		   length: "14,16", 
		   prefixes: "300,301,302,303,304,305,36,38,55",
		   checkdigit: true};
cards [3] = {name: "AmEx", 
		   length: "15", 
		   prefixes: "34,37",
		   checkdigit: true};
cards [4] = {name: "Discover", 
		   length: "16", 
		   prefixes: "6011,65",
		   checkdigit: true};
//  cards [5] = {name: "CarteBlanche", 
//               length: "14", 
//               prefixes: "300,301,302,303,304,305,36,38",
//               checkdigit: true};
//  cards [6] = {name: "JCB", 
//               length: "15,16", 
//               prefixes: "3,1800,2131",
//               checkdigit: true};
//  cards [7] = {name: "enRoute", 
//               length: "15", 
//               prefixes: "2014,2149",
//               checkdigit: true};
//  cards [8] = {name: "Solo", 
//               length: "16,18,19", 
//               prefixes: "6334, 6767",
//               checkdigit: true};
//  cards [9] = {name: "Switch", 
//               length: "16,18,19", 
//               prefixes: "4903,4905,4911,4936,564182,633110,6333,6759",
//               checkdigit: true};
//  cards [10] = {name: "Maestro", 
//               length: "16", 
//               prefixes: "5020,6",
//               checkdigit: true};
//  cards [11] = {name: "VisaElectron", 
//               length: "16", 
//               prefixes: "417500,4917,4913",
//               checkdigit: true};

var ccErrors = new Array ()

ccErrors [1] = "Unknown card type";
ccErrors [2] = "Credit card number is in invalid format";
ccErrors [3] = "Credit card number is invalid";
ccErrors [4] = "Credit card number has an inappropriate number of digits";

function validateCC(CCNumber){
	if (CCNumber.length<10) return 3;
// Check that the number is numeric
var cardexp = /^[0-9]{13,19}$/;
	if (!cardexp.exec(CCNumber))  return 2;  //Invalid characters in the CC number
//Identify the CC type
var cardId = -1
	for (var i=0; i<cards.length; i++) {
		prefix = cards[i].prefixes.split(",");
		for (var j=0; j<prefix.length; j++) {
			var exp = new RegExp ("^" + prefix[j]);
			if (exp.test(CCNumber)){
				cardId = i;
				break;
			}
		}
		//if (cardId!=-1) break;
	}

	if (cardId == -1) return 1 // Invalid credit card type
// Verify the validation or checksum
	if (cards[cardId].checkdigit) {// checksum
		var checksum = 0;                                  // running checksum total
		var mychar = "";                                   // next char to process
		var j = 1;                                         // takes value of 1 or 2

		// Process each digit one by one starting at the right
		var calc;
		for (i = CCNumber.length - 1; i >= 0; i--) {
			// Extract the next digit and multiply by 1 or 2 on alternative digits.
			calc = Number(CCNumber.charAt(i)) * j;
			// If the result is in two digits add 1 to the checksum total
			if (calc > 9) {
				checksum = checksum + 1;
				calc = calc - 10;
			}
			// Add the units element to the checksum total
			checksum = checksum + calc;
			// Switch the value of j
			if (j ==1) {j = 2} else {j = 1};
		} 
		// All done - if checksum is divisible by 10, it is a valid modulus 10.
		// If not, report an error.
		if (checksum % 10 != 0)  return 3; //Invalid numeric values 
	} // checksum 
//Indentify the length is correct
	var LengthValid
	var lengths = cards[cardId].length.split(",");
	for (j=0; j<lengths.length; j++) {
		if (CCNumber.length == lengths[j]){
			LengthValid = true;
			break;
		}
  	}
	if (!LengthValid) return 4;
	return 0; 
}

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.0
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && document.getElementById) x=document.getElementById(n); return x;
}
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
function MM_nbGroup(event, grpName) { //v3.0
  var i,img,nbArr,args=MM_nbGroup.arguments;
  if (event == "init" && args.length > 2) {
    if ((img = MM_findObj(args[2])) != null && !img.MM_init) {
      img.MM_init = true; img.MM_up = args[3]; img.MM_dn = img.src;
      if ((nbArr = document[grpName]) == null) nbArr = document[grpName] = new Array();
      nbArr[nbArr.length] = img;
      for (i=4; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) {
        if (!img.MM_up) img.MM_up = img.src;
        img.src = img.MM_dn = args[i+1];
        nbArr[nbArr.length] = img;
    } }
  } else if (event == "over") {
    document.MM_nbOver = nbArr = new Array();
    for (i=1; i < args.length-1; i+=3) if ((img = MM_findObj(args[i])) != null) {
      if (!img.MM_up) img.MM_up = img.src;
      img.src = (img.MM_dn && args[i+2]) ? args[i+2] : args[i+1];
      nbArr[nbArr.length] = img;
    }
  } else if (event == "out" ) {
    for (i=0; i < document.MM_nbOver.length; i++) {
      img = document.MM_nbOver[i]; img.src = (img.MM_dn) ? img.MM_dn : img.MM_up; }
  } else if (event == "down") {
    if ((nbArr = document[grpName]) != null)
      for (i=0; i < nbArr.length; i++) { img=nbArr[i]; img.src = img.MM_up; img.MM_dn = 0; }
    document[grpName] = nbArr = new Array();
    for (i=2; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) {
      if (!img.MM_up) img.MM_up = img.src;
      img.src = img.MM_dn = args[i+1];
      nbArr[nbArr.length] = img;
  } }
}
function MM_validateForm() { //v4.0
var i,p,q,nm,test,num,min,max,errors='',args=MM_validateForm.arguments;

	for (i=0; i<(args.length-2); i+=3) { 
		test=args[i+2]; 
		val=MM_findObj(args[i]);
		if (val) { 
			nm=val.name; 
			if ((val=val.value)!="") {
				if (test.indexOf('CreditCard')!=-1){
					var ccerror = validateCC(val);
					if (ccerror!=0) errors+='- ' +  ccErrors[ccerror] + '\n';
				} else if (test.indexOf('isEmail')!=-1) { 
					p=val.indexOf('@');
					if (p<1 || p==(val.length-1)) errors+='- '+nm+' must contain an e-mail address.\n';
				} else if (test!='R') {
						if (isNaN(val)) errors+='- '+nm+' must contain a number.\n';
					if (test.indexOf('inRange') != -1) { 
						p=test.indexOf(':');
						min=test.substring(8,p); 
						max=test.substring(p+1);
						if (val<min || max<val) errors+='- '+nm+' must contain a number between '+min+' and '+max+'.\n';
					}
				} 
			} else if (test.charAt(0) == 'R') errors += '- '+nm+' is required.\n';  
		}
	}
	if (errors) alert('The following error(s) occurred:\n'+errors);
	return (errors == '');
}

//-->

