DEV Community

Saulo Dias
Saulo Dias

Posted on • Edited on

Generating Valid Code 128 Barcodes with Javascript

To generate a valid Code 128 barcode you need to follow some rules. It must contain a start chararacter, that indicates which character set you want to represent; the data characters, the characters that will be encoded; the checksum, a single character for error checking; and finally, a stop character, to indicate the end of the barcode.

In the ID Automation Code 128 Barcode Font User Manual
you can find detailed instructions on what those characters (Start and Stop) are and how to generate a checksum for the data you want to encode.

For most applications Set B or C is what you want. Set B contains digits, uppercase and lowercase letters, and some special characters. Set C is used to represent numbers from 00 to 99, which is useful when you want to represent huge strings of numbers. Set A contains digits, uppercase letters, and a bunch of control characters, which might be useful in some specific applications.

You can also switch between the three code sets in the same barcode, as there are control characters for that purpose in each set. However, this will not be covered in this post.

To generate the valid code we must pass the text to be encoded to the encodeToCode128 function.

const checkbox = document.getElementById('withtext')

function toSetC(text) {
  return text.match(/\d{2}/g).map((ascii, index) => {
    var codeC = Number(ascii);
    var charCode = codeC > 94 ? codeC + 100 : codeC + 32;
    return String.fromCharCode(charCode)
  }).join('');
}

function checkSum128(data, startCode) {
  var sum = startCode;
  for (var i = 0; i < data.length; i++) {
    var code = data.charCodeAt(i);
    var value = code > 199 ? code - 100 : code - 32;
    sum += (i + 1) * (value);
  }

  var checksum = (sum % 103) + 32;
  if (checksum > 126) checksum = checksum + 68 ;
  return String.fromCharCode(checksum);
}

function encodeToCode128(text, codeABC = "B") {
  var startCode = String.fromCharCode(codeABC.toUpperCase().charCodeAt() + 138);
  var stop = String.fromCharCode(206);

  text = codeABC == 'C' && toSetC(text) || text;

  var check = checkSum128(text, startCode.charCodeAt(0) - 100);

  text = text.replace(" ", String.fromCharCode(194));

  return startCode + text + check + stop;
}

function renderBarcodes(withText = true) {
  var barcodeElements = document.querySelectorAll(".barcode");
  var codes = [];
  barcodeElements.forEach((e) => {
    var code = e.attributes["data-barcode"]?.value;
    if (!code) return;
    var set = e.attributes["data-set"]?.value;
    e.innerHTML = encodeToCode128(code, set);
    e.classList.toggle('with-text', withText)
  });
}

renderBarcodes();

checkbox.addEventListener('change', (event) => {
  renderBarcodes(event.currentTarget.checked)
});
Enter fullscreen mode Exit fullscreen mode

To generate the valid barcode we just add the barcode class to an empty div and pass the data-barcode attribute with the data we want. This is a completely arbitrary parameter name, but it is the parameter the renderBarcodes function will look for.

   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Libre+Barcode+128">

   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Libre+Barcode+128+Text">

   <input type="checkbox" id="withtext" name="Show Barcode With Text" checked>
   <label for="withtext">Show Barcode With Text</label>
   <br /> <br />

   <div class="barcode" data-barcode="https://dev.to/saulodias"></div>
   <br />
   This code contains only digits, and can have a shorter barcode when using Set C
   <div class="barcode" data-barcode="0123456789"></div>
   <br />
   Same data as the barcode above but with a shorter barcode.
   <div class="barcode" data-barcode="0123456789" data-set="C"></div>
Enter fullscreen mode Exit fullscreen mode

Here are is the CSS to apply correctly apply the Libre Barcode fonts used.

.barcode {
  font-family: "Libre Barcode 128", "Courier New", Courier, monospace;
  font-weight: normal;
  font-size: 52px;
  white-space: nowrap;
}

.with-text {
  font-family: "Libre Barcode 128 Text";
}
Enter fullscreen mode Exit fullscreen mode

See the JS Fiddle Example here.

Length Optimization

Here is an example switching code set for optimization

The challenge is to find the best combination to optimize the number of characters used, making the barcode shorter. This is explained in [more details on Wikipedia.]
To decide when switch to code C I have used the criteria in this Wikipedia Page

Additional notes

If you prefer, the fonts used in the example can be downloaded here:

On Stack Overflow Taw implemented this in C#. I used his implementation as reference.

P.S. When generating server-side PDFs, which is something I needed to do you might need to install the fonts to the server, if you have any trouble with font-face and/or the CDN fonts. In any case I do not like to use CDN fonts for several reasons out of the scope of this post.

Top comments (7)

Collapse
 
janborup profile image
Jan Borup Coyle • Edited

There is an error in your short barcode has the number is 95, 96, 97, 98 og 99.
Then the barcode is formated with a wrong char.
/Cheers

Image description

Collapse
 
saulodias profile image
Saulo Dias • Edited

This bug had been caught but I only corrected it in the version with the dynamic optimization. I have updated the jsfiddle and the code in the post. Thanks for reporting!

Collapse
 
robhumphries5 profile image
Rob Humphries

Thanks so much, this code is extremely helpful.

I am having a problem where Libre Barcode 128 Text is showing the checksum character in the text.

When I scan the barcode it is read correctly, but the checksum text is showing.

Any ideas?

Collapse
 
saulodias profile image
Saulo Dias

Hello Rob. I'm glad this has been helpful to you. Can you give me a reproduction of the error on jsfiddle? You can fork the example given, make changes and send it back here. I'll see what I can do.

Collapse
 
freddyvial profile image
Freddyvial

Image description

Thread Thread
 
freddyvial profile image
Freddyvial

no es 199 es 194 en el checkSum:

var value = code > 194 ? code - 100 : code - 32;

Collapse
 
freddyvial profile image
Freddyvial

Muchas gracias, estaba como loco buscando esto, cuando me di cuenta que usar el code128 es un poco mas complejo, si quieres leer los códigos desde el html con un app movil. Dios te bendiga siempre.
Nota: .charCodeAt()= charCodeAt(0) :=>
var startCode = String.fromCharCode(codeABC.toUpperCase().charCodeAt(0) + 138);

Nota: renderBarcodes(event.currentTarget.checked)
=>
renderBarcodes((event.target as HTMLInputElement).checked)