javascript

Javascript Code128 Barcode

This is a departure from my usual postings. I’m not going to give a whole lot of background or write up on it. Instead I’m just going to give you the code. You either need code that can generate code128 or you don’t. The code provided here should give you a working page that will generate a Code128 barcode in either horizontal or vertical format. I’ve tested the generation in IE (7+) and Firefox (3.5) and tested the reading of the barcode with the AABBY OCR software.

My reason for pursuing this was because I’ve got several different methods to read barcodes, but not many to generate them. One involves special fonts, which is fine for server based generation, but when I need to generate a barcode based on data that is on a web page, the options were lacking.

This code is derived from the code at: Code128. The updates that I’m providing are:

  1. Original Page does not display barcode in IE 7+. This has been fixed.
  2. Separated CSS and Javascript into separate files
  3. Removed requirement of base2.js library (I didn’t see any value-add to include this large of a library)
  4. Added code to support Vertical Barcode (top to bottom)
  5. The original form generation was a bit odd and convoluted, so it has been simplified

For the most part, except for removing the base2.js dependencies, I left the javascript in-tact. I must say that some of it is exceptionally well-done by the original author.

To switch between vertical layout and horizontal layout, change the css class of the div element with the “barcode” id in the base128.htm file. Please note that the vertical barcode sets a z-index of 99. This means that you should set a left margin for your base elements, otherwise the barcode will float over the top and be unreadable.

***The HTML file: code128.htm

<html>
<head>
<link rel="StyleSheet" href="barcode.css" type="text/css" />
<script src="barcode.js"></script>
<script type="text/javascript">
function encode()
{
  var strValue = document.getElementById("barcode_input").value;
  var strBarcodeHTML = code128(strValue);
  document.getElementById("barcode").innerHTML = strBarcodeHTML;
}
</script>
</head>
<div class="barcode128v" id="barcode"></div>
<br /><br />
<input style="margin-left:45px" type="text" id="barcode_input"></input>
<input type="button" value="Encode" onclick="encode()"/>
</html>

***The CSS file: barcode.css

/*==============================================================
                CODE 128 styles
===============================================================*/

/* ------------------- Horizontal Barcode -------------------- */
.barcode128h  {
    clear: both;
    padding: 0 10px /*quiet zone*/;
    overflow: auto;
    height: 0.35in   /*size*/;
}

.barcode128h div {
    /*float: left;*/
    height: 0.2 in  /*size*/;
    display: inline;
}

.barcode128h label {
    clear: both;
    display: block;
    text-align: center;
    font: 0.125in/100% helvetica /*size*/;
}

.barcode128h .bar1 { border-left: 1px solid black }
.barcode128h .bar2 { border-left: 2px solid black }
.barcode128h .bar3 { border-left: 3px solid black }
.barcode128h .bar4 { border-left: 4px solid black }
.barcode128h .space0 { margin-right: 0px }
.barcode128h .space1 { margin-right: 1px }
.barcode128h .space2 { margin-right: 2px }
.barcode128h .space3 { margin-right: 3px }
.barcode128h .space4 { margin-right: 4px }

/* ------------------- Vertical Barcode --------------------- */
.barcode128v  {
    /*float: top;*/
    clear: left;
    position: absolute;
    padding: 10 0px /*quiet zone*/;
    overflow: auto;
    width: 30px  /*size*/;
    z-index: 99;

}

.barcode128v div {
    float: top;
    display: block;
    /*width: 20px;
    height:0px;*/
}

.barcode128v label {
    clear: right;
    display: block;
    text-align: center;
    font: 0.125in/100% helvetica /*size*/;
    writing-mode: tb-rl;
    filter: flipH() flipV();
}

.barcode128v .bar1 { border-top: 1px solid black; z-index: 99;}
.barcode128v .bar2 { border-top: 2px solid black; z-index: 99;}
.barcode128v .bar3 { border-top: 3px solid black; z-index: 99;}
.barcode128v .bar4 { border-top: 4px solid black; z-index: 99;}
.barcode128v .space0 { margin-bottom: 0px; z-index: 99; }
.barcode128v .space1 { margin-bottom: 1px; z-index: 99; }
.barcode128v .space2 { margin-bottom: 2px; z-index: 99; }
.barcode128v .space3 { margin-bottom: 3px; z-index: 99; }
.barcode128v .space4 { margin-bottom: 4px; z-index: 99; }

***The Javascript file: barcode.js

BARS       = [212222,222122,222221,121223,121322,131222,122213,122312,132212,221213,221312,231212,112232,122132,122231,113222,123122,123221,223211,221132,221231,213212,223112,312131,311222,321122,321221,312212,322112,322211,212123,212321,232121,111323,131123,131321,112313,132113,132311,211313,231113,231311,112133,112331,132131,113123,113321,133121,313121,211331,231131,213113,213311,213131,311123,311321,331121,312113,312311,332111,314111,221411,431111,111224,111422,121124,121421,141122,141221,112214,112412,122114,122411,142112,142211,241211,221114,413111,241112,134111,111242,121142,121241,114212,124112,124211,411212,421112,421211,212141,214121,412121,111143,111341,131141,114113,114311,411113,411311,113141,114131,311141,411131,211412,211214,211232,23311120];
START_BASE = 38
STOP       = 106 //BARS[STOP]==23311120 (manually added a zero at the end)

var fromType128 = {
    A: function(charCode) {
        if (charCode>=0 && charCode<32)
            return charCode+64;
        if (charCode>=32 && charCode<96)
            return charCode-32;
        return charCode;
    },
    B: function(charCode) {
        if (charCode>=32 && charCode<128)
            return charCode-32;
        return charCode;
    },
    C: function(charCode) {
        return charCode;
    }
};

function code128(code, barcodeType) {
    if (arguments.length<2)
        barcodeType = code128Detect(code);
    if (barcodeType=='C' && code.length%2==1)
        code = '0'+code;
    var a = parseBarcode128(code,  barcodeType);
    return bar2html128(a.join('')) ;//+ '<label>' + code + '</label>';
}


function code128Detect(code) {
    if (/^[0-9]+$/.test(code)) return 'C';
    if (/[a-z]/.test(code)) return 'B';
    return 'A';
}

function parseBarcode128(barcode, barcodeType) {
    var bars = [];
    bars.add = function(nr) {
        var nrCode = BARS[nr];
        this.check = this.length==0 ? nr : this.check + nr*this.length;
        this.push( nrCode || format("UNDEFINED: %1->%2", nr, nrCode) );
    };

    bars.add(START_BASE + barcodeType.charCodeAt(0));
    for(var i=0; i<barcode.length; i++)
    {
        var code = barcodeType=='C' ? +barcode.substr(i++, 2) : barcode.charCodeAt(i);
        converted = fromType128[barcodeType](code);
        if (isNaN(converted) || converted<0 || converted>106)
            throw new Error(format("Unrecognized character (%1) at position %2 in code '%3'.", code, i, barcode));
        bars.add( converted );
    }
    bars.push(BARS[bars.check % 103], BARS[STOP]);

    return bars;
}

function format(c){
    var d=arguments;
    var e= new RegExp("%([1-"+(arguments.length-1)+"])","g");
    return(c+"").replace(e,function(a,b){return d[b]})
}

function bar2html128(s) {
    for(var pos=0, sb=[]; pos<s.length; pos+=2)
    {
        sb.push('<div class="bar' + s.charAt(pos) + ' space' + s.charAt(pos+1) + '"></div>');
    }
    return sb.join('');
}

HTH

Advertisements

Searching in Javascript arrays

I have a problem.  Namely, that I work with Lawson Portal which requires IE.  There are times when writing a custom HTML or Design Studio page when I store data in Arrays and then have to look up data from them later.   Since IE doesn’t support the .indexOf for Arrays, how to find the info I need?  When dealing with large lists of data, using loops just isn’t feasible, especially if I’m going to use the Array a lot.  I could prototype the indexOf feature, but I have an easier way (depending on the data).

An example of this is what I’m working on currently.  Our Finance department doesn’t want to give security access to the Lawson AP90 screen (Invoice lookup) to everyone in the enterprise because there are sensitive invoices (Legal bills, Employee re-imbursements, etc.), and there’s no good way to secure them.  It’s a legitimate concern, but the problem is people need invoice information to manage and they shouldn’t have to wait on AP or Finance to get their information.

Luckily, our Finance department maintains attributes on each Accounting unit for Manager, VP, etc. that contains the user name. (For those of you who are not Lawson users, an Accounting unit is roughly equivalent to a department code). The most efficient solution is to only let users see invoices that are related to their department by creating an object that acts like an array of Accounting units when the page loads, and then comparing the Accounting Unit(s) for the requested invoice to the Object to determine whether to display or not.  So this brings us to the question of “How do I search a javascript Array effectively?”.

The answer is use an Associative Array — which javascript does not support (technically). What we actually do is to assign properties to javascript’s Object.
(If you want to prototype the indexOf, see this link.)

Say we have a list of values like:  100000,100001,115000,950000.

Normally we would do something like:

var arrAU = new Array(100000,100001,115000,950000);
function lookupAU(strAU) {
  for (var i=0;i<arrAU.length;i++)
  {
    if(arrAU[i] == strAU)
      return true;
  }
    return false;
}

But what happens when we hit the VP or President level and there are hundreds or thousands of Accounting Units?

Instead we set the Object property to the Accounting Unit and set the value to some small value (because the value is irrelevant to us).

var arrAU = "";
arrAU['100000'] = true;
arrAU['100001'] = true;
arrAU['115000'] = true;
arrAU['950000'] = true;

function lookupAU(strAU) {
  if (arrAU[strAU] != undefined)
    return true;
  else
    return false;
}

So the answer to how to search arrays is that we don’t use arrays. The result is that we don’t waste the resources on the loop, and we get right to what we want in an IE supported manner. Please keep in mind that the .length property will not return the length because this is not an Array.

HTH

For those of you who use Lawson and would like to know more about the full process, feel free to leave a comment and I’ll be happy to share.