JavaScript / jQuery VIN验证器

时间:2014-10-16 14:33:11

标签: javascript jquery regex coldfusion

有没有人创建过VIN验证器?我正在尝试创建一个文本框,用户将在其中输入车辆识别号码,然后JS / jQuery将验证其是否正确,以防他们输入数字错误。

我是JS / jQuery的新手,并且已经找到了一些例子,但当然无法使它们正常工作......任何有任何想法或建议的人都会非常感激,特别是如果你能说出来的话我如何设置下面的内容才能正常工作!

注意:isVin() functioncflib.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 &amp; 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>

测试代码:

    <cfoutput>
<cfset vin = "1GNDM19ZXRB170064">
#vin#: #isVin(vin)#<br />
<cfset vin = "1FAFP40634F172825">
#vin#: #isVin(vin)#<br />
</cfoutput>

2 个答案:

答案 0 :(得分:13)

如果您要为在北美销售的车辆 1 解码VIN,您可以验证以下内容:

  1. VIN长度为17位
  2. 如果是17位数,那么校验位(第9位)是正确的
  3. 由于您将在用户输入VIN时实时检查VIN,因此提高效率非常重要。这意味着在用户输入时快速失败。虽然您可以使用正则表达式完成此任务,但它比仅仅检查VIN的长度要慢得多。一旦VIN长达17位,您就可以验证校验位(顺便提一下,它本身也比正则表达式更快 - 见下文)。

    正则表达式不适合VIN验证,原因如下:

    1. 性能。它没有简单地检查长度那么快,而速度的折衷并不能在很大程度上提高准确性,因为你无法验证校验位。

    2. 精度。虽然这是真的,你可以确保VIN在长度和有效字符方面符合正确的模式,这是不够的。 KNDJB723025140702是有效的VIN,KNDJB723025140703不是(唯一的区别是最后一个数字)。正则表达式解决方案将显示两个VIN都有效,第二个是假阳性,因此不正确。

    3. 维基百科有really good script用于执行校验位验证,如果VIN是17位,则仅通过验证校验位也很​​快失败。

      In my own testing,下面的脚本比使用正则表达式验证VIN要快得多(大约40倍),并且它还具有返回准确结果的额外好处。

      $(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]在欧盟销售的车辆通常不使用校验位,对于某些车辆甚至可以是18位数(梅赛德斯)。

答案 1 :(得分:10)

这是使用正则表达式的客户端解决方案。

&#13;
&#13;
$(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);
}
&#13;
<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>
&#13;
&#13;
&#13;