DEV Community 👩‍💻👨‍💻

Saulo Dias
Saulo Dias

Posted on • Updated 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(data) {
  var str = data.match(/\d{2}|./g).map((ascii) => {
    if(ascii.length == 1) {
        return String.fromCharCode(200) + ascii;
    }
    return String.fromCharCode(Number(ascii) + 32);
  }).join('');
  return str;
}

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 (0)

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

⭐️🎀 JavaScript Visualized: Promises & Async/Await

async await