2012-11-28 29 views

Trả lời

19

EDIT Tôi cũng đã tạo mô-đun npm, có thể tìm thấy trên github.

Tôi đã tạo một thư viện nhỏ, hỗ trợ EAN8, EAN12, EAN13, EAN14, EAN18, GTIN12, GTIN13 và GTIN14.

Nó hoạt động bên trong node.js và tất cả các trình duyệt hiện đại.

barcoder.js:

/*! 
* Barcoder 
* Copyright (c) 2013 mifitto GmbH <[email protected]> 
* MIT Licensed 
*/ 

(function() { 

    'use strict'; 

    /** 
    * Library version. 
    */ 

    var version = '1.1.0'; 

    /** 
    * Supported formats 
    */ 

    var minValidLength = 6; 
    var maxValidLength = 18; 
    var usualValidChars = /^\d+$/; 

    var formats = { 
    'ean8' : { validChars : /^\d+$/, validLength : 8 }, 
    'ean12' : { validChars : /^\d+$/, validLength : 12 }, 
    'ean13' : { validChars : /^\d+$/, validLength : 13 }, 
    'ean14' : { validChars : /^\d+$/, validLength : 14 }, 
    'ean18' : { validChars : /^\d+$/, validLength : 18 }, 
    'gtin12' : { validChars : /^\d+$/, validLength : 12 }, 
    'gtin13' : { validChars : /^\d+$/, validLength : 13 }, 
    'gtin14' : { validChars : /^\d+$/, validLength : 14 } 
    }; 

    /** 
    * Validates the checksum (Modulo 10) 
    * GTIN implementation factor 3 
    * 
    * @param {String} value The barcode to validate 
    * @return {Boolean} 
    * @api private 
    */ 

    var validateGtin = function(value) { 

    var barcode = value.substring(0, value.length - 1); 
    var checksum = parseInt(value.substring(value.length - 1), 10); 
    var calcSum = 0; 
    var calcChecksum = 0; 

    barcode.split('').map(function(number, index) { 
     number = parseInt(number, 10); 
     if (value.length % 2 === 0) { 
     index += 1; 
     } 
     if (index % 2 === 0) { 
     calcSum += number; 
     } 
     else { 
     calcSum += number * 3; 
     } 
    }); 

    calcSum %= 10; 
    calcChecksum = (calcSum === 0) ? 0 : (10 - calcSum); 

    if (calcChecksum !== checksum) { 
     return false; 
    } 

    return true; 

    }; 

    /** 
    * Barcoder class 
    * 
    * @param {string} format See formats 
    * @param {Object} options Valid option `enableZeroPadding`, defaults to `true` 
    * @api public 
    */ 

    var Barcoder = function (format, options) { 

    if (format && !formats[format]) throw new Error('"format" invalid'); 

    this.format = (format) ? formats[format] : 'autoSelect'; 
    this.options = (options) ? options : { enableZeroPadding : true }; 

    if (!this.options.enableZeroPadding) { 
     this.options.enableZeroPadding = true; 
    } 

    }; 

    /** 
    * Validates a barcode 
    * 
    * @param {string} barcode EAN/GTIN barcode 
    * @return {Boolean} 
    * @api public 
    */ 

    Barcoder.prototype.validate = function(barcode) { 

    var self = this; 

    if (self.format === 'autoSelect') { 

     if (barcode.length < minValidLength || barcode.length > maxValidLength) { 
     return false; 
     } 

     var isValidGtin = validateGtin(barcode); 
     var paddedBarcode = barcode; 
     var successfullyPadded = false; 

     if (!isValidGtin) { 
     var possiblyMissingZeros = maxValidLength - barcode.length; 
     while(possiblyMissingZeros--) { 
      paddedBarcode = '0' + paddedBarcode; 
      if (validateGtin(paddedBarcode)) { 
      isValidGtin = true; 
      successfullyPadded = true; 
      break; 
      } 
     } 
     } 

     return { 
     possibleType: (barcode.length > 8) ? 'GTIN' + barcode.length : 'EAN8/padded GTIN', 
     isValid: isValidGtin 
     }; 

    } 

    var validChars = self.format.validChars; 
    var validLength = self.format.validLength; 
    var enableZeroPadding = self.options.enableZeroPadding; 

    if (validChars.exec(barcode) === null) { 
     return false; 
    } 

    if (enableZeroPadding && barcode.length < validLength) { 
     var missingZeros = validLength - barcode.length; 
     while(missingZeros--) { 
     barcode = '0' + barcode; 
     } 
    } 
    else if (!enableZeroPadding && barcode.length != validLength) { 
     return false; 
    } 
    else if (barcode.length > validLength) { 
     return false; 
    } 

    return validateGtin(barcode); 

    }; 

    /** 
    * Export 
    */ 

    if ('undefined' !== typeof module && module.exports) { 
    module.exports = Barcoder; 
    exports.version = version; 
    } 

    if ('undefined' === typeof ender) { 
    this['Barcoder'] = Barcoder; 
    } 

    if ('function' === typeof define && define.amd) { 
    define('Barcoder', [], function() { 
     return Barcoder; 
    }); 
    } 

}).call(this); 

Cài đặt:

$ npm install barcoder 

Cách sử dụng:

var Barcoder = require('barcoder'); 

var ean1 = '0016T20054453'; 
var ean2 = '9330071314999'; 

var validator = new Barcoder('ean13'); 

console.log('%s ean1 is valid: %s', ean1, validator.validate(ean1)); 
console.log('%s ean2 is valid: %s', ean1, validator.validate(ean2)); 

// or /w automatic type selection 

validator = new Barcoder(); 

var validation1 = validator.validate(ean1); 
var validation2 = validator.validate(ean2); 

console.log('%s is valid: %s and has guessed type: %s', ean1, validation1.isValid, validation1.possibleType); 
console.log('%s is valid: %s and has guessed type: %s', ean2, validation2.isValid, validation2.possibleType); 
11

Tôi không chắc chắn lý do tại sao, nhưng @mo osgummi của giải pháp đã không hoạt động chính xác cho tôi. Ngoài ra, tôi muốn cả hai số tính mã mới cũng như xác minh mã cũ. Tôi đã kết thúc với điều này, mà tôi đã xác minh được làm việc trong các trình duyệt của tôi ít nhất:

function eanCheckDigit(s){ 
    var result = 0; 
    for (counter = s.length-1; counter >=0; counter--){ 
     result = result + parseInt(s.charAt(counter)) * (1+(2*(counter % 2))); 
    } 
    return (10 - (result % 10)) % 10; 
} 
+0

Bạn có thể thay thế biểu thức Math.pow bằng cách đơn giản hơn (1+ (2 * (truy cập% 2)) với cùng kết quả – ThunderGr

+0

Rất tốt! Đã trả lời cập nhật –

+0

Có vẻ là lỗi khung trong dòng bốn. – user1876422

4

Đây là một phiên bản ngắn có thể kiểm tra xem các chữ số EAN13 séc có giá trị:

var checkSum = ean.split('').reduce(function(p,v,i) { 
    return i % 2 == 0 ? p + 1 * v : p + 3 * v; 
    }, 0); 
    if (checkSum % 10 != 0) { 
    alert('error'); 
    } 
+0

mát mẻ, thats chính xác những gì tôi cần.Chỉ cần thêm ean = "" + ean; để đúc nó như là chuỗi để sử dụng chức năng .split – trojan

0

tôi m xin lỗi nếu mã này là một chút quá lâu, nhưng đây là những gì tôi có cho việc xác minh một mã vạch EAN13:

function isBarcode(barcode) { 
    if (typeof barcode === 'number') { 
     throw 'RuntimeError: Barcode MUST NOT be in number format' 
    } else if (barcode.length!==12) { 
     throw 'RuntimeError: String length is not 12' 
    }; 
    var _= barcode.toString().split("") 
    var _1 = 0 
    var _2 = 0 
    var __ 
    for ($=0;$<=10;++$) { 
     _1+=+_[$] 
    };for ($=10;$>=0;$-=2) { 
     _2+=+_[$] 
    };_2*=2 
    var _3 = _1+_2 
    __=+_3.toString().substring(1,2) 
    if (__>9) { 
     __=+_3.toString().substring(1,2) 
    } else if (__===0) { 
     __=10 
    }; 
    __=10-__ 
    if (__===+_[11]) { 
     return true 
    } 
    return false 
}; 
+0

Hãy giải thích lý do tại sao điều này hoạt động.Điều này sẽ ngăn chặn OP chỉ đơn giản là sao chép và dán mã của bạn mà không hiểu cách nó hoạt động, hoặc nếu nó là ở tất cả phù hợp cho nhiệm vụ của họ trong tầm tay. – rayryeng

+0

@rayryeng: Tôi sẽ không sao chép bất kỳ thứ gì mà không yêu cầu quyền;) Tôi thích các giải pháp thông minh, nhưng tôi nghĩ đoạn mã này không thực sự có thể duy trì và/hoặc có thể đọc được. Tôi cũng hoan nghênh lời giải thích. – dom

+0

@dom - ahahaha Tôi đồng ý :) – rayryeng

0

đây là giải pháp của tôi, kiểm tra mã vạch chiều dài khác nhau sử dụng các đặc điểm kỹ thuật để tính toán chec k chữ số cuối cùng (xem chú thích):

// ean/gtin validation for 8, 12, 13 & 14 digit barcodes 
function codeOnBlur(barcode) { 

    var barcodeLengthArr = [8, 12, 13, 14]; 
    var allowedChars = new RegExp(/\d{8,14}/); // >7 & <15 
    // put numbers in array and convert to type Int. 
    var barcodeArray = barcode.split(''); 
    for(var i = 0; i < barcodeArray.length; i++) { 
     barcodeArray[i] = parseInt(barcodeArray[i], 10); 
    } 
    // get the last digit for checking later 
    var checkDigit = barcodeArray.slice(-1)[0]; 
    // we'll need a to compare it to this: 
    var remainder = 0; 

    // check if input (barcode) is in the array and check against the regex. 
    if (($.inArray(barcode.length, barcodeLengthArr) > -1) && (allowedChars.test(barcode))) { 
     console.log("barcodeArray ", barcodeArray, " :: checkDigit ", checkDigit); 

     // Pop the last item from the barcode array, test if the length is 
     // odd or even (see note on calculating the check digit) and 
     // multiply each item in array based in position: 
     var total = 0; 
     barcodeArray.pop(); 
     // odd length after pop 
     if (barcodeArray.length % 2 === 1) { 
      for (var i = barcodeArray.length - 1; i >= 0; i--) { 
       barcodeArray[i] = i % 2 === 0 ? barcodeArray[i] * 3 : barcodeArray[i] * 1; 
       total += barcodeArray[i]; 
      } 
     // even length after pop 
     } else if (barcodeArray.length % 2 === 0) { 

      for (var i = barcodeArray.length - 1; i >= 0; i--) { 
       barcodeArray[i] = i % 2 === 0 ? barcodeArray[i] * 1 : barcodeArray[i] * 3; 
       total += barcodeArray[i]; 
      } 
     } else { 
      // validation passed = false 
     } 
     // calculate the remainder of totalrounded up to nearest multiple of 10: 
     remainder = (Math.ceil((total + 1)/10) * 10) - total; 
     console.log("loop total = ", total, ", remainder: ", remainder); 

     if (remainder === checkDigit) { 
      //validation passed = true; 
      return; 
     } else { 
       //validation passed = false; 
     } 

    } else { 
     //validation Passed = false; 
    } 
} 

Tôi chắc chắn mã này có thể được sắp xếp gọn gàng lên một số :)

thủ kiểm tra "chút liêm" hoặc check digit:

 barcode: 13: 4 0 1 1 2 0 0 2 9 6 9 0 8 
       8:     5 0 8 1 8 9 0 7 

    multiplier:  3 1 3 1 3 1 3 1 3 1 3 1 check digit 

Để lấy mã 8 chữ số làm việc ngược:

0*1 + 9*3 + 8*1 + 1*3 + 8*1 + 0*3 + 5*1 = 73 

Difference from 73 to 80 is 7 (the specification will have you round up to 
the nearest power of 10). 

7 vừa là số kiểm tra và thời gian còn lại của 80-7 3.

Các vấn đề liên quan