2012-11-28 21 views

risposta

19

EDIT Ho anche creato un modulo npm, che può essere trovato su github.

Ho creato una piccola libreria che supporta EAN8, EAN12, EAN13, EAN14, EAN18, GTIN12, GTIN13 e GTIN14.

Funziona all'interno di node.js e di tutti i browser moderni.

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); 

Installazione:

$ npm install barcoder 

Usage:

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

io non so perché, ma @mo la soluzione di osgummi non ha funzionato correttamente per me. Inoltre vorrei entrambi i codici calcolare e verificare vecchi. Ho finito con questo, che ho verificato di lavorare nel mio browser atleast:

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

È possibile sostituire l'espressione Math.pow con una più semplice (1+ (2 * (contatore% 2)) con lo stesso risultato – ThunderGr

+0

Nice! Risposta aggiornata –

+0

Sembra essere un errore di parentesi nella riga 4. Una parentesi di chiusura troppe cose. – user1876422

4

Ecco una versione corta che può controllare se la cifra EAN13 di controllo è valida:

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

cool, questo è esattamente quello di cui avevo bisogno. Basta aggiungere ean = "" + ean; per lanciarlo come stringa per usare la funzione .split – trojan

0

I' mi dispiace se questo codice è un po 'troppo lungo, ma questo è quello che ho per la verifica di un codice a barre 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

Spiega perché funziona.Ciò impedirà all'OP di copiare e incollare semplicemente il codice senza capire come funziona, o se è del tutto adatto al loro compito. – rayryeng

+0

@rayryeng: Non copierò nulla senza chiedere permessi;) Mi piacciono le soluzioni intelligenti, ma penso che questo pezzo di codice non sia realmente mantenibile e/o leggibile. Vorrei anche una spiegazione. – dom

+0

@dom - ahahaha Sono d'accordo :) – rayryeng

0

Ecco la mia soluzione, il controllo di diversi codici a barre di lunghezza utilizzando la specifica per calcolare il chec k cifra alla fine (vedi nota):

// 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; 
    } 
} 

sono certo questo codice può essere riordinato un po ':)

controllando manualmente la "bit integrità" o controllare cifre:

 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 

Per prendere il codice a 8 cifre a ritroso:

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 è sia la cifra di controllo e la restante 80-7 3.

Problemi correlati