Come posso verificare se una stringa è un codice a barre EAN/GTIN valido in JavaScript?Come convalidare un codice a barre EAN/GTIN in JavaScript
Ho bisogno di controlli per EAN8, EAN12, EAN13, EAN14, EAN18 e anche GTIN12, GTIN13, GTIN14.
Come posso verificare se una stringa è un codice a barre EAN/GTIN valido in JavaScript?Come convalidare un codice a barre EAN/GTIN in JavaScript
Ho bisogno di controlli per EAN8, EAN12, EAN13, EAN14, EAN18 e anche GTIN12, GTIN13, GTIN14.
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);
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;
}
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');
}
cool, questo è esattamente quello di cui avevo bisogno. Basta aggiungere ean = "" + ean; per lanciarlo come stringa per usare la funzione .split – trojan
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
};
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
@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
@dom - ahahaha Sono d'accordo :) – rayryeng
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.
È possibile sostituire l'espressione Math.pow con una più semplice (1+ (2 * (contatore% 2)) con lo stesso risultato – ThunderGr
Nice! Risposta aggiornata –
Sembra essere un errore di parentesi nella riga 4. Una parentesi di chiusura troppe cose. – user1876422