// JavaScript Document

var g_prd;
var g_tdays;

$j(window).load( function() {
	if ($j("#_postdata").length > 0) {
		PreperetoCheckAvailability("form-step1");
	}
	
	$j("#VolusionLiveChat table tr:eq(1)").addClass("hidden");
	
	$j(".livesupport-tc").css( { "left": ($j(".livesupport-topimage").position().left-12) + "px", "top":$j(".livesupport-topimage").position().top + "px" } );
	$j(".newsletter-tc").css( { "left": ($j(".newsletter-topimage").position().left-12) + "px", "top":$j(".newsletter-topimage").position().top + "px" } );	
});

function DrawPlayer() {
	$f("player", "templates/wt/default/JavaScripts/Flowplayer/flowplayer-3.1.5.swf", {
		plugins: {
			controls:  {display: 'none' }
		},
		
		playlist: [
			{
				url: "templates/wt/default/SafariVideoPresentation.flv",
				autoPlay: true,  
				autoBuffering: true,  
				
				onFinish: function() {
					this.unload();
				}
			}	
		]	
	});	
}

$j(document).ready(function() {
	$j("ul.nav").supersubs({ minWidth: 12, maxWidth: 27, extraWidth: 1 }).superfish({ delay: 200, speed: 200, autoArrows: false, dropShadows: false });
							
	$j("ul.nav a").corner("3px");
	$j("ul.home .round").corner("5px");
	$j("li ul").corner("bottom right 3px");
	$j("li.fleet li:not(.total) a").append("<span>View car fleet</span>");
							
	if ($j.browser.msie) {
		$j("input[type=radio]").css('border', 'none');	
		$j("a.round:not(.right .round)").corner("3px");
	} else {
		$j("a.round").corner("3px");
	}
	
	$j(".navbackground").css( { "left": ($j("ul.nav").position().left) + "px", "top":$j("ul.nav").position().top + "px", "width":$j("ul.nav").width()+16 + "px" } );
							
	$j("a.play").click(function() { 
		$j(".preview").fadeOut('fast', function() {
			DrawPlayer();
			$j('#player').fadeIn('fast', function() {
				
			});
		});
		return false;
	})
	
	function spd() { $j(this).next().fadeIn("fast"); }
	function hpd() { $j(this).next().fadeOut("fast"); }
	
	var config1 = {    
		over: spd,
		timeout: 500,
		out: hpd
	};
	
	$j("a.pdetails").hoverIntent(config1);
	$j("form#newsletter .round").click(function () { $j("form#newsletter").submit(); })
							
	var contactoptions = { 
		target: '.status',
		resetForm: true
	};
							
	$j("form#contact input.confirm").click(function () { 
		if (validate("contact")) { $j("#contact").ajaxSubmit(contactoptions); }
		return false; 
	});		
							
	$j("ul.search a.select").click(function() {
		$j("#restep1").dialog('open');
		return false;
	})
	
	$j("#restep1").dialog({
		width: 310,
		autoOpen: false,
		resizable: false,
		stack: false,
		modal: true,
		buttons: {
			"Cancel": function() {
				$j(this).dialog('close');
			},
			'Check Availability': function() {
				$j("#restep1 #form-step1").submit();
				$j(this).dialog('close');
			}
		}
	});
							
	Initialize_Events_After_Products_Load();	
							
	$j(document).ajaxSend(function() { loader(true); });
	$j(document).ajaxStop(function() { loader(false); });
							
	InitializeRes_Steps();
	
	$j("a.homesubmit").click(function() {
		$j("#book").submit();
		return false;
	})
	
	$j('.lytebox').lightBox();

	Initialize_Top_Form();

	$j('.datetime input').datepicker({
		duration: '',
		//showTime: true,
		constrainInput: false,
		//stepMinutes: 15,  
		//stepHours: 1, 
		changeMonth: true,
		changeYear: true,
		//altTimeField: '',  
		dateFormat: 'dd/mm/yy',
		//time24h: true,
		onClose: function(dateText, inst) {  
			if ($j(this).attr("rel") == "startdate") {
				$j('.datetime input[rel="enddate"]').val(dateText);
			}
		}
	});
	
	$j("ul.home li:nth-child(even)").addClass("nomargin");
	
});

function Initialize_Top_Form() {
	$j(".down .listbox select").jListbox();

	$j('.down .elementwrap').mouseenter(function() { $j(this).addClass('focused'); })
	$j('.down .elementwrap').mouseleave(function() { $j(this).removeClass('focused'); });
	
	$j(".down form.inlinelabels .row").each(function(el) {
		templabel = $j(this).find("label").html();
		$j(this).find("input").val(templabel);
		$j(this).find("input").click(function () { $j(this).val(""); })
	})
}

function gotostep(stepstr) {
	$j('#steps li').removeClass("current");
	$j('#steps li .helpcl').remove();
	
	$j('#steps li[rel='+stepstr+']').addClass("current");
	
	if (stepstr != "step1") { $j('#steps li[rel='+stepstr+']').prepend('<span class="helpcl"></span>');	}	
	
	$j('.steps').fadeOut("fast", function() {
		$j('div#'+stepstr+'').fadeIn("fast");
	});
	
	return false;
}

function calc_extras() {
	var thiscost = 0;
	
	$j(".extras input[type=radio][cost!='0']:checked").each(function() {
		costtype = $j(this).attr("cost-type");
		ecost = $j(this).attr("cost");
		
		if (costtype == "perday") {
			ecost = ecost * g_tdays;
		}
		
		thiscost += parseFloat(ecost);
	})
		
	return thiscost;
}

function After_Success_Submit() {
	$j("#step4 a.back, table.cart, a.saveres, #steps, .terms, #creditcardinfo").addClass("hidden");
	$j(".success-payment").fadeIn("hidden");
	$j(".payonline").removeClass("hidden");
	
	//step(1);
}

function sgval(obj) {
	return $j("select[name="+obj+"]").val();
}

function InitializeRes_Steps() {
	var simple_submit_options = { 
		target: '#resid',
		success: function(responseText, statusText, xhr, $form)  { 
			After_Success_Submit();
		} 
	}; 
	
	$j("a.saveres").click(function () { 
		var checked = $j('input[name=iagree]:checked').val() != undefined;
	
		if (validate("creditcardinfo")) { 
			if (checked) {
				$j("input[name=creditcard_name]").val(sgval("creditcard"));
				$j("input[name=creditcard_number]").val(gval("card_number"));
				$j("input[name=creditcard_holder]").val(gval("holder"));
				$j("input[name=creditcard_valid_month]").val(sgval("validmonth"));
				$j("input[name=creditcard_valid_year]").val(sgval("validyear"));
				$j("input[name=creditcard_cvv]").val(gval("cvv"));
	
				$j("#form-step3").ajaxSubmit(simple_submit_options); 
			}
			else {
				message("Warning", "You must accept our terms &amp; conditions to procceed with your request.");
			}
		}

		return false; 
	});
	
	currentstep = $j('ul#steps li.current').attr("rel");
	gotostep(currentstep);
	
	$j(".extras input[type=radio]").click(function () { 
		transfer_prices_data($j("input[name=_pcost]").val(), calc_extras());
	})
	
	$j("#step2 a.confirm").click(function () { 
		if (validate("form-step2")) {
			transfer_driver_info();
			
			var notices1 = get_extras_for_notice();
			var notices2 = search_pairs("#step2 ul.cart_notice li", "span", "strong");
			final_notices = notices1 + notices2;
			
			Add2Cart(SelectedProduct(), 1, final_notices, gval("cost"));
			step(1);
		}
		return false;
	})
	
	$j("#step3 a.confirm").click(function () { 
		if (validate("form-step3")) {
			$j.ajax({
				url: "basefiles/FormSubmit.asp?type=cart&action=get&lg_id=1",
				cache: false,
				success: function(html){
					$j(".products").html(html);
					
					var config = {    
						over: infoshow,
						timeout: 500,
						out: infohide
					};
					
					$j("a.pmoreinfo").hoverIntent(config);
					
				
					function infoshow(){ $j(this).find(".pinfo").fadeIn("fast"); }
					function infohide(){ $j(this).find(".pinfo").fadeOut("fast"); }		
					
					
					step(1);
				}
			});
		} 
		return false;
	})
	
	$j("ul#steps li a").click(function () { 
		newstep = parseInt($j(this).parent().attr("rel").replace("step", ""));		
		oldstep = parseInt($j('ul#steps li.current').attr("rel").replace("step", ""));	
		
		if (newstep < oldstep) {
			gotostep("step"+newstep);
		}
		return false;
	})
	
	$j("a.price").live('click', function () { return false; })
	
	$j("a.select").live('click', function () { 
		booklink = $j(this);								   
										   
		pid = $j(this).parent().parent().attr("id");
		
		startdate = $j("input#a-pdate").val();
		enddate = $j("input#a-rdate").val();
		
		offeractionvalue = $j(this).parent().parent().find("a.price").attr("offeractionvalue");
		offeractionid = $j(this).parent().parent().find("a.price").attr("offeractionid");
		
		$j.ajax({
			url: "basefiles/FormSubmit.asp?type=pricetable&startdate="+startdate+"&enddate="+enddate+"&pid="+pid+"&offeractionid="+offeractionid+"&offeractionvalue="+offeractionvalue+"",
			cache: false,
			success: function(html){ 
				html_ = html.split("###")[1];
				html_a = html.split("###")[0];
			
				$j("li#"+pid+" .pricetable tbody").html(html_a); 
				$j("li#"+pid+" .pricetable tbody tr:odd").addClass("odd");
			
				if (html_ != "False") {
					transfer_data(pid);
					step(1);
				} else {
					$j(".pl").html(booklink.prev().prev().clone());
					
					$j("#dialog-confirm").dialog({
						resizable: false,
						width: 327,
						modal: true,
						buttons: {
							"No, Thanks": function() {
								$j(this).dialog('destroy');
							},
							'Book this car anyway': function() {
								thisstartdate = booklink.parent().find(".pricetable table tbody tr:first-child td:nth-child(2)").html();
								thisenddate = booklink.parent().find(".pricetable table tbody tr:last-child td:nth-child(2)").html();
								
								$j("input#a-pdate").val(date_to_mysql_format(thisstartdate));
								$j("input#a-rdate").val(date_to_mysql_format(thisenddate));
								
								$j(this).dialog('destroy');
								transfer_data(pid);
								step(1);
							}
						}
					});
				}
			}
		});	

		return false;
	})
	
	$j("a.back").click(function () { 
		step(-1);
		return false;
	})
	
	$j("#step1 a.next").click(function () { 
		PreperetoCheckAvailability("form-step1");
		return false;
	})
	
	$j("ul#steps li").each(function(i) {
		if (i == 0) { $j(this).addClass("round first"); } else { if ($j(this).hasClass('current')) { $j(this).prepend('<span class="helpcl"></span>'); }}
		var tmp = parseInt(i) + 1;							
		$j(this).prepend('<span class="nom">'+tmp+'</span>');
	});
}

function date_to_mysql_format(tempdate) {
	temp = tempdate.split("/");
	newdate = temp[2] +"-"+ temp[1] +"-"+ temp[0] + " 00:00";
	return newdate;
}

function transfer_data(x) {
	/* LOCATIONS */
	g_prd = x;
	g_tdays = $j("li#"+x+" .pricetable table tbody tr").size();
	
	plocation_text = $j("select#plocation :selected").text();
	rlocation_text = $j("select#rlocation :selected").text();
	
	$j("strong[rel=rplace]").html(rlocation_text);
	$j("strong[rel=pplace]").html(plocation_text);
	
	$j("input[name=_plocation]").val($j("select#plocation").val());
	$j("input[name=_rlocation]").val($j("select#rlocation").val());
	
	/* DATES */	
	pdate = $j("input#a-pdate").val();
	rdate = $j("input#a-rdate").val();
	
	$j("strong[rel=rdate]").html(rdate);
	$j("strong[rel=pdate]").html(pdate);
	$j("input[name=_pdate]").val(pdate);
	$j("input[name=_rdate]").val(rdate);
	
	/* VEHICLE INFO */	
	carimage = $j("#products li#"+x+" a.lytebox img").attr("src");
	carimagelink = $j("#products li#"+x+" a.lytebox").attr("href");
	carbrand = $j("#products li#"+x+" .car-title").attr("brand");
	carmodel = $j("#products li#"+x+" .car-title").attr("model");
	cargroup = $j("#products li#"+x+" .car-group").html();
	
	$j("input[name=_pid]").val(x);
	$j(".vehicle-info strong[rel=model]").html(carmodel);
	$j(".vehicle-info strong[rel=brand]").html(carbrand);
	$j(".vehicle-info strong[rel=group]").html(cargroup);
	$j(".vehicle-info img.selcar").attr("src", carimage);
	$j(".vehicle-info a.lytebox").attr("href", carimagelink);
	
	/* PRICES */
	transfer_prices_data(calculate_product_price(x), 0);
}

function SelectedProduct() {
	return $j("input[name=_pid]").val();
}

function gval(inputname) {
	return $j("input[name="+inputname+"]").val();
}

function transfer_prices_data(product_price, extra_price) {
	totalprice = parseFloat(product_price) + parseFloat(extra_price);
	
	//alert(product_price);
	
	$j("strong[rel=carprice]").html(formatCurrency(product_price));

	$j("strong[rel=extraprice], strong[rel=totalprice]").fadeOut("fast", function() { 
		$j("strong[rel=extraprice]").html(formatCurrency(extra_price));
		$j("strong[rel=totalprice]").html(formatCurrency(totalprice));
		$j("strong[rel=extraprice], strong[rel=totalprice]").fadeIn("fast"); 
	});

	$j("input[name=cost]").val(totalprice);
	$j("input[name=_pcost]").val(product_price);
	$j("input[name=_ecost]").val(extra_price);
}

function transfer_driver_info() {
	drivers_title = $j("select[name=_info0] :selected").text();
	drivers_fname = $j("input[name=_info1]").val();
	drivers_lname = $j("input[name=_info2]").val();
	drivers_lnumber = $j("input[name=_info3]").val();
	drivers_age = $j("input[name=_info4]").val();

	$j("strong[rel=title]").html(drivers_title);
	$j("strong[rel=fname]").html(drivers_fname);
	$j("strong[rel=lname]").html(drivers_lname);
	$j("strong[rel=lnumber]").html(drivers_lnumber);
	$j("strong[rel=age]").html(drivers_age);
}

function step(x) {
	curstep = $j("#steps li.current").attr("rel");
	curstep_id = parseInt(curstep.split("step")[1]) + x;
	newstep = "step"+curstep_id+""
	gotostep(newstep);
}

function DateExtract(x, dstr) {
	y = dstr.split(" ");
	return y[x];
}

function PreperetoCheckAvailability(formname) {
	if (validate(formname)) {
		t = DateExtract(0, gval("pdate")).split("/");
		y = t[2] + "-" + t[1] + "-" + t[0] + " " + sgval("time1") + ":" + sgval("sec1");
		$j('input[name=a-pdate]').val(y);
		
		r = DateExtract(0, gval("rdate")).split("/");
		s = r[2] + "-" + r[1] + "-" + r[0] + " " + sgval("time2") + ":" + sgval("sec2");
		$j('input[name=a-rdate]').val(s);
		
		var pdate = gval("a-pdate");
		var rdate = gval("a-rdate");
		
		pdate1 = new Date(pdate.replace(/-/g,"/"));
		rdate1 = new Date(rdate.replace(/-/g,"/"));
		totaldays = Math.round((rdate1-pdate1)/(1000*60*60*24));
				
		if (totaldays > 0) {
			CheckAvailability(pdate, rdate);
		} else {
			if (totaldays < 0) {
				message("Warning", "The return date cannot be earlier than the pickup.")
			} else {
				message("Warning", "The return date cannot be the same as the pickup date.")
			}
		}
		
	} else {
		message("Warning", "Please fill in the required fields.");
	}	
}

function CheckAvailability(startdate, enddate) {
	query = "basefiles/FormSubmit.asp?type=availability&startdate="+startdate+"&enddate="+enddate+"";	
	
	$j("#products ul").html("");
	
	$j.ajax({
		url: query,
		cache: false,
		success: function(html){
			if (html == "") {
				message("Search Results", "There are no cars available on this date period.");
			} else {
				$j("#products ul").html(html);
				Initialize_Events_After_Products_Load();
				$j('.lytebox').lightBox();
			}
		}
	});		
}

function ShowPriceTable() {
	CountTR = $j(this).prev().find("table tbody tr").size();
	
	if (CountTR == 0) {
		startdate = $j("input#a-pdate").val();
		enddate = $j("input#a-rdate").val();
		
		offeractionvalue = $j(this).attr("offeractionvalue");
		offeractionid = $j(this).attr("offeractionid");
		
		pid = $j(this).parent().parent().attr("id");

		$j.ajax({
			url: "basefiles/FormSubmit.asp?type=pricetable&startdate="+startdate+"&enddate="+enddate+"&pid="+pid+"&offeractionid="+offeractionid+"&offeractionvalue="+offeractionvalue+"",
			cache: false,
			success: function(html){ 
				html_ = html.split("###")[0];
			
				$j("li#"+pid+" .pricetable tbody").html(html_); 
				$j("li#"+pid+" .pricetable tbody tr:odd").addClass("odd");
				
				$j("li#"+pid+" .pricetable tfoot td.total").html(formatCurrency(calculate_product_price(pid)));	
				
				if ($j.browser.version == "7.0") {
					liheight = $j("li#"+pid+"").height(); 
					
					$j("li#"+pid+" .pricetable").css({ 
						"height": liheight-50+"px", 
						"overflow": "auto",
						"overflow-x": "hidden"
					}); 
				}
			}
		});			
	}
	$j(this).prev().fadeIn("fast");
}

function HidePriceTable() {
	$j(this).prev().fadeOut("fast");
}

function Initialize_Events_After_Products_Load() {
	var config = {    
		over: ShowPriceTable,
		timeout: 500,
		out: HidePriceTable
	};
	
	$j("a.price").hoverIntent(config);
}

function loader(x) { 
	if (x) { 
		$j(".rightc").addClass("rel");
		$j(".loading").fadeIn("fast");
		
		//$j("body").append('<div class="ui-widget-overlay" style="width: 1263px; height: 1264px; z-index: 1001;"></div>');
	} else { 
		$j(".loading").fadeOut("fast"); 
		$j(".rightc").removeClass("rel");

		//$j("body .ui-widget-overlay").remove();
	}
}

function calculate_product_price(pid) {
	thiscost = 0;
	
	//thiscost = $j("li#"+pid+" .pricetable tbody tr:last td:last").attr("rel").replace(",",".");
	
	$j("li#"+pid+" .pricetable tbody tr").each(function(i) {
		tmp = $j(this).children("td:nth-child(3)").attr("rel");
		thiscost += parseFloat(tmp.replace(",","."));
	});
	
	return thiscost;
}

function formatCurrency(num) {
	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num))
	num = "0";
	sign = (num == (num = Math.abs(num)));
	num = Math.floor(num*100+0.50000000001);
	cents = num%100;
	num = Math.floor(num/100).toString();
	if(cents<10)
	cents = "0" + cents;
	for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
	num = num.substring(0,num.length-(4*i+3))+','+
	num.substring(num.length-(4*i+3));
	return (((sign)?'':'-') + num + '.' + cents + ' &#8364;');
}

function Add2Cart(pid, qty, notice, price) {
	$j.ajax({
		url: "basefiles/FormSubmit.asp?type=cart&action=add&pid="+pid+"&qty="+qty+"&notice="+notice+"&price="+price+"",
		cache: false,
		success: function(html){
			return html;
		}
	});
}

function validate(formid) { 
	valid = true;
	var validationErrors = new Array ();

	// TEXTBOX CHECK
	$j('#'+formid+' .validate').each( function(){
		tmpobj = $j(this).find("input, textarea, select");
		if (tmpobj.val() == "") { IsNull = true; } else { IsNull = false; }
		
		object_label = $j("label[for="+tmpobj.attr("name")+"]").html();
		
		var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;  
		IsEmail = emailPattern.test(tmpobj.val());  

		IsString = isNaN(tmpobj.val());
		
		CheckReq = $j(this).hasClass("required");
		CheckNom = $j(this).hasClass("number");
		CheckEmail = $j(this).hasClass("email");
		CheckCreditCard = $j(this).hasClass("creditcard");
		
		// NULL CHECK
		if ((CheckReq) && (IsNull)) {
			validationErrors.push("<b>"+object_label+"</b>: Is required");
			$j(this).addClass("invalid-req");
		} else {
			$j(this).removeClass("invalid-req");
		}
		
		// NUMBER CHECK
		if ((CheckNom) && (IsString)) {
			validationErrors.push("<b>"+object_label+"</b>: Is not a valid number");
			$j(this).addClass("invalid-nom"); 
		} else {
			$j(this).removeClass("invalid-nom");
		}
		
		// EMAIL CHECK
		if (CheckEmail && (!IsEmail)) {
			validationErrors.push("<b>"+object_label+"</b>: Is not a valid email address");
			$j(this).addClass("invalid-email");
		} else {
			$j(this).removeClass("invalid-email");
		}
		
		// CREDIT CARD CHECK
		if (CheckCreditCard) {
			CreditCardNumber = tmpobj.val();
			CreditCardName = $j("select[name="+tmpobj.attr("cartnamefield")+"]").val();
			CreditCard_is_valid = checkCreditCard(CreditCardNumber, CreditCardName);
			
			if (CreditCard_is_valid) {
				$j(this).removeClass("invalid-creditcard");	
			} else {
				validationErrors.push("<b>"+object_label+"</b>: Is not a valid credit card");
				$j(this).addClass("invalid-creditcard");		
			}
		}		
	});
	
	if (validationErrors.length > 0) {
		valid = false;
		tempmessage = validationErrors.join("<br>");
		message("Form errors ("+validationErrors.length+")", tempmessage);
	}
	return valid;
}

function message(title, str) {
	$j("#simple-message").dialog("destroy");
	$j("#simple-message p").html(str);
	$j("#simple-message").dialog({
		resizable: false,
		title: title,
		modal: true,
		buttons: {
			Ok: function() {
				$j(this).dialog('close');
			}
		}
	});
}

function get_extras_for_notice() {
	var result = "";
	$j("#step2 .extras .row").each(function(i) {
		tempcolumn = $j(this).find("label.title").html();
		tempvalue = $j(this).find("input[type=radio]:checked").next().html();
		
		if (tempcolumn != null) { result += tempcolumn + " " + tempvalue + "---"; }
	});
		
	return result;
}

function search_pairs(obj_to_search, column_obj, value_obj) {
	var result = "";
	$j(""+obj_to_search+"").each(function(i) {
		tempcolumn = $j(this).find(""+column_obj+"").html();
		tempvalue = $j(this).find(""+value_obj+"").html();
		
		if (tempcolumn != null) { result += tempcolumn + " " + tempvalue + "---"; }
	});
	return result;
}

var ccErrorNo = 0;
var ccErrors = new Array ()

ccErrors [0] = "Unknown card type";
ccErrors [1] = "No card number provided";
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 checkCreditCard(cardnumber, cardname) {
     
  // 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 - must be same as user's
  //  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: "305, 36, 38, 54,55",
               checkdigit: true};
  cards [3] = {name: "CarteBlanche", 
               length: "14", 
               prefixes: "300,301,302,303,304,305",
               checkdigit: true};
  cards [4] = {name: "AmEx", 
               length: "15", 
               prefixes: "34,37",
               checkdigit: true};
  cards [5] = {name: "Discover", 
               length: "16", 
               prefixes: "6011,622,64,65",
               checkdigit: true};
  cards [6] = {name: "JCB", 
               length: "16", 
               prefixes: "35",
               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: "12,13,14,15,16,18,19", 
               prefixes: "5018,5020,5038,6304,6759,6761",
               checkdigit: true};
  cards [11] = {name: "VisaElectron", 
               length: "16", 
               prefixes: "417500,4917,4913,4508,4844",
               checkdigit: true};
  cards [12] = {name: "LaserCard", 
               length: "16,17,18,19", 
               prefixes: "6304,6706,6771,6709",
               checkdigit: true};
               
  // Establish card type
  var cardType = -1;
  for (var i=0; i<cards.length; i++) {

    // See if it is this card (ignoring the case of the string)
    if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
      cardType = i;
      break;
    }
  }
  
  // If card type not found, report an error
  if (cardType == -1) {
     ccErrorNo = 0;
     return false; 
  }
   
  // Ensure that the user has provided a credit card number
  if (cardnumber.length == 0)  {
     ccErrorNo = 1;
     return false; 
  }
    
  // Now remove any spaces from the credit card number
  cardnumber = cardnumber.replace (/\s/g, "");
  
  // Check that the number is numeric
  var cardNo = cardnumber
  var cardexp = /^[0-9]{13,19}$/;
  if (!cardexp.exec(cardNo))  {
     ccErrorNo = 2;
     return false; 
  }
       
  // Now check the modulus 10 check digit - if required
  if (cards[cardType].checkdigit) {
    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 = cardNo.length - 1; i >= 0; i--) {

    
      // Extract the next digit and multiply by 1 or 2 on alternative digits.
      calc = Number(cardNo.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)  {
     ccErrorNo = 3;
     return false; 
    }
  }  

  // The following are the card-specific checks we undertake.
  var LengthValid = false;
  var PrefixValid = false; 
  var undefined; 

  // We use these for holding the valid lengths and prefixes of a card type
  var prefix = new Array ();
  var lengths = new Array ();
    
  // Load an array with the valid prefixes for this card
  prefix = cards[cardType].prefixes.split(",");
      
  // Now see if any of them match what we have in the card number
  for (i=0; i<prefix.length; i++) {
    var exp = new RegExp ("^" + prefix[i]);
    if (exp.test (cardNo)) PrefixValid = true;
  }
      
  // If it isn't a valid prefix there's no point at looking at the length
  if (!PrefixValid) {
     ccErrorNo = 3;
     return false; 
  }
    
  // See if the length is valid for this card
  lengths = cards[cardType].length.split(",");
  for (j=0; j<lengths.length; j++) {
    if (cardNo.length == lengths[j]) LengthValid = true;
  }
  
  // See if all is OK by seeing if the length was valid. We only check the 
  // length if all else was hunky dory.
  if (!LengthValid) {
     ccErrorNo = 4;
     return false; 
  };   
  
  // The credit card is in the required format.
  return true;
}

