问题
Has anyone ever created a VIN Validator? I am trying to create a textbox where the user will enter in a Vehicle Identification Number and then JS/jQuery will validate if its correct or not in case they mistype the number.
I am very new to JS/jQuery and have found some examples but of course have not been able to get them to work correctly... Any one with any ideas or suggestions it would be greatly appreciated, especially if you can tell me how to set up what I have below to work properly!
Note: The isVin() function is courtesy of cflib.org
HTML:
<label name="vin">VIN</label>
<input type="text" name="vin" />
ColdFusion:
<cfscript>
/**
* US Vehicle Identification Number (VIN) validation.
* version 1.0 by Christopher Jordan
* version 1.1 by RHPT, Peter Boughton & Adam Cameron (original function rejected valid VINs)
*
* @param v VIN to validate (Required)
* @return Returns a boolean.
* @author Christopher Jordan (cjordan@placs.net)
* @version 1, February 19, 2013
*/
function isVIN(v) {
var i = "";
var d = "";
var checkDigit = "";
var sum = 0;
var weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
var transliterations = {
a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8,
j = 1, k = 2, l = 3, m = 4, n = 5, p = 7, r = 9,
s = 2, t = 3, u = 4, v = 5, w = 6, x = 7, y = 8, z = 9
};
var vinRegex = "(?x) ## allow comments
^ ## from the start of the string
## see http://en.wikipedia.org/wiki/Vehicle_Identification_Number for VIN spec
[A-Z\d]{3} ## World Manufacturer Identifier (WMI)
[A-Z\d]{5} ## Vehicle decription section (VDS)
[\dX] ## Check digit
[A-Z\d] ## Model year
[A-Z\d] ## Plant
\d{6} ## Sequence
$ ## to the end of the string
";
if (! REFindNoCase(vinRegex, arguments.v)) {
return false;
}
for (i = 1; i <= len(arguments.v); i++) {
d = mid(arguments.v, i, 1);
if (! isNumeric(d)) {
sum += transliterations[d] * weights[i];
} else {
sum += d * weights[i];
}
}
checkDigit = sum % 11;
if (checkDigit == 10) {
checkDigit = "x";
}
return checkDigit == mid(arguments.v, 9, 1);
}
</cfscript>
Test Code:
<cfoutput>
<cfset vin = "1GNDM19ZXRB170064">
#vin#: #isVin(vin)#<br />
<cfset vin = "1FAFP40634F172825">
#vin#: #isVin(vin)#<br />
</cfoutput>
回答1:
Here's a client-side solution using Regular Expressions.
$(function() {
$("#vin").on("keyup blur", function() {
if (validateVin($("#vin").val()))
$("#result").html("That's a VIN");
else
$("#result").html("Not a VIN");
}).trigger("blur");
});
function validateVin(vin) {
var re = new RegExp("^[A-HJ-NPR-Z\\d]{8}[\\dX][A-HJ-NPR-Z\\d]{2}\\d{6}$");
return vin.match(re);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label name="vin">VIN</label>
<input type="text" id="vin" value="1FAFP40634F172825" />
<span id="result"></span>
回答2:
If you're decoding VINs for vehicles sold in North America1, you can validate the following:
- That the VIN is 17 digits in length
- If 17 digits, that the check digit (9th position) is correct
As you'll be checking the VIN in real time as the user types it in, it's important to be efficient. This means failing fast while the user is typing it in. While you can use regex for this task, it's far slower than simply checking the VIN's length. Once the VIN is 17 digits long then you can validate the check digit (which, incidentally, is itself also faster than regex - see below).
Regular expressions are not a good fit for VIN validation for a couple reasons:
Performance. It's not as fast as simply checking the length, and the trade-off for speed doesn't net you that much of an improvement in accuracy because you can't validate the check digit.
Accuracy. While it's true you can ensure a VIN meets the correct pattern in terms of length and valid characters, that is not enough.
KNDJB723025140702is a valid VIN whileKNDJB723025140703is not (the only difference is the last number). A regex solution will show both VINs as being valid, with the second being a false-positive and therefore incorrect.
Wikipedia has a really good script for performing check digit validation that also fails quickly by only validating the check digit if the VIN is 17 digits.
In my own testing, the script below is much, must faster (roughly 40x) than using regex to validate a VIN, and it has the added benefit of returning accurate results.
$(function() {
var $ctrl = $('#vin'),
$msg = $('#validation-message');
$ctrl.keyup(function() {
if (validateVin($ctrl.val())) {
$msg.html("VIN is valid!");
} else {
$msg.html("VIN is not valid");
}
});
});
function validateVin(vin) {
return validate(vin);
// source: https://en.wikipedia.org/wiki/Vehicle_identification_number#Example_Code
// ---------------------------------------------------------------------------------
function transliterate(c) {
return '0123456789.ABCDEFGH..JKLMN.P.R..STUVWXYZ'.indexOf(c) % 10;
}
function get_check_digit(vin) {
var map = '0123456789X';
var weights = '8765432X098765432';
var sum = 0;
for (var i = 0; i < 17; ++i)
sum += transliterate(vin[i]) * map.indexOf(weights[i]);
return map[sum % 11];
}
function validate(vin) {
if (vin.length !== 17) return false;
return get_check_digit(vin) === vin[8];
}
// ---------------------------------------------------------------------------------
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
VIN:
<input id="vin" type="text" />
<span id="validation-message"></span>
[1] Vehicles sold in the EU don't typically use a check digit, and for some cars can even be 18 digits in length (Mercedes).
来源:https://stackoverflow.com/questions/26407015/javascript-jquery-vin-validator