jQuery.validator.addMethod('creditcard3',function(value,element,param){
	
	// the param is a jquery selector string to hold the returned card types
	
	// Define Accepted Card Types
	var cards = new Array();
	cards[0] = {cardName:'Visa',lengths:'13,16',prefixes:'4',checkdigit:true},
	cards[1] = {cardName:'MasterCard',lengths:'16',prefixes:'51,52,53,54,55',checkdigit:true},
	cards[2] = {cardName:'AmEx',lengths:'15',prefixes:'34,37',checkdigit:true},
	cards[3] = {cardName:'Discover',lengths:'16',prefixes:'6011,650',checkdigit:true}
	
	
	
	// Check for Well-formed Card Number
	var cardNum = value.replace(/[\D\s-]/g,'');
	var cardExp = /^[0-9]{13,16}$/;
	
	if (cardNum.length == 0) {return false;}			// Card number has no length.
	if (!cardExp.exec(cardNum)) {return false;}			// Card number has characters or is wrong length.
	
	
	
	// CheckDigit Algorithm
	var cdChecksum = 0;
	var cdMyChar = '';
	var cdJ = 1;
	var cdCalc;
	for (i = cardNum.length - 1; i >= 0; i--) {
		cdCalc = Number(cardNum.charAt(i)) * cdJ;
		if (cdCalc > 9) {
			cdChecksum = cdChecksum + 1;
			cdCalc = cdCalc - 10;
		}
		cdChecksum = cdChecksum + cdCalc;
		if (cdJ == 1) {cdJ = 2} else {cdJ = 1}
	}
	
	if (cdChecksum % 10 != 0) {return false;}			// CheckDigit is not mod10.
	
	
	
	// Check Card Number Prefixes
	var prefixValid = new Array();
	for (i in cards) {
		var prefixes = new Array();
		prefixes = cards[i].prefixes.split(',');
		for (pi in prefixes) {
			var exp = new RegExp('^'+prefixes[pi]);
			if (exp.test(cardNum)) prefixValid.push(i);
		}
	}
	
	if (prefixValid.length == 0) {return false;}		// Card number prefix doesn't match card types.
	
	
	
	// Check Card Number Lengths
	var lengthValid = new Array();
	$(prefixValid).each(function(i,v) {
		var lengths = new Array();
		lengths = cards[v].lengths.split(',');
		for (li in lengths) {
			if (cardNum.length == lengths[li]) lengthValid.push(cards[v].cardName);
		}
	});
	/*
	var lengthValid = new Array();
	for (i in prefixValid) {
		var lengths = new Array();
		lengths = cards[i].lengths.split(',');
		for (li in lengths) {
			if (cardNum.length == lengths[li]) lengthValid.push(cards[i].cardName);
		}
	}
	*/
	if (lengthValid.length == 0) {return false;}		// Card number length doesn't match card types.
	
	// Return Card Type
	if ($(param).length) {$(param).val(lengthValid.join(' '));}
	
	if (lengthValid.length >= 1) {return true;}			// Card number length & prefix matches multiple card types.
	if (lengthValid.length == 1) {return true;}			// Valid Card!!
	
});