UPCE.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Encoding documentation:
  2. // https://en.wikipedia.org/wiki/Universal_Product_Code#Encoding
  3. //
  4. // UPC-E documentation:
  5. // https://en.wikipedia.org/wiki/Universal_Product_Code#UPC-E
  6. import encode from './encoder';
  7. import Barcode from "../Barcode.js";
  8. import { checksum } from './UPC.js';
  9. const EXPANSIONS = [
  10. "XX00000XXX",
  11. "XX10000XXX",
  12. "XX20000XXX",
  13. "XXX00000XX",
  14. "XXXX00000X",
  15. "XXXXX00005",
  16. "XXXXX00006",
  17. "XXXXX00007",
  18. "XXXXX00008",
  19. "XXXXX00009"
  20. ];
  21. const PARITIES = [
  22. ["EEEOOO", "OOOEEE"],
  23. ["EEOEOO", "OOEOEE"],
  24. ["EEOOEO", "OOEEOE"],
  25. ["EEOOOE", "OOEEEO"],
  26. ["EOEEOO", "OEOOEE"],
  27. ["EOOEEO", "OEEOOE"],
  28. ["EOOOEE", "OEEEOO"],
  29. ["EOEOEO", "OEOEOE"],
  30. ["EOEOOE", "OEOEEO"],
  31. ["EOOEOE", "OEEOEO"]
  32. ];
  33. class UPCE extends Barcode{
  34. constructor(data, options){
  35. // Code may be 6 or 8 digits;
  36. // A 7 digit code is ambiguous as to whether the extra digit
  37. // is a UPC-A check or number system digit.
  38. super(data, options);
  39. this.isValid = false;
  40. if(data.search(/^[0-9]{6}$/) !== -1){
  41. this.middleDigits = data;
  42. this.upcA = expandToUPCA(data, "0");
  43. this.text = options.text ||
  44. `${this.upcA[0]}${data}${this.upcA[this.upcA.length - 1]}`;
  45. this.isValid = true;
  46. }
  47. else if(data.search(/^[01][0-9]{7}$/) !== -1){
  48. this.middleDigits = data.substring(1, data.length - 1);
  49. this.upcA = expandToUPCA(this.middleDigits, data[0]);
  50. if(this.upcA[this.upcA.length - 1] === data[data.length - 1]){
  51. this.isValid = true;
  52. }
  53. else{
  54. // checksum mismatch
  55. return;
  56. }
  57. }
  58. else{
  59. return;
  60. }
  61. this.displayValue = options.displayValue;
  62. // Make sure the font is not bigger than the space between the guard bars
  63. if(options.fontSize > options.width * 10){
  64. this.fontSize = options.width * 10;
  65. }
  66. else{
  67. this.fontSize = options.fontSize;
  68. }
  69. // Make the guard bars go down half the way of the text
  70. this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
  71. }
  72. valid(){
  73. return this.isValid;
  74. }
  75. encode(){
  76. if(this.options.flat){
  77. return this.flatEncoding();
  78. }
  79. else{
  80. return this.guardedEncoding();
  81. }
  82. }
  83. flatEncoding(){
  84. var result = "";
  85. result += "101";
  86. result += this.encodeMiddleDigits();
  87. result += "010101";
  88. return {
  89. data: result,
  90. text: this.text
  91. };
  92. }
  93. guardedEncoding(){
  94. var result = [];
  95. // Add the UPC-A number system digit beneath the quiet zone
  96. if(this.displayValue){
  97. result.push({
  98. data: "00000000",
  99. text: this.text[0],
  100. options: {textAlign: "left", fontSize: this.fontSize}
  101. });
  102. }
  103. // Add the guard bars
  104. result.push({
  105. data: "101",
  106. options: {height: this.guardHeight}
  107. });
  108. // Add the 6 UPC-E digits
  109. result.push({
  110. data: this.encodeMiddleDigits(),
  111. text: this.text.substring(1, 7),
  112. options: {fontSize: this.fontSize}
  113. });
  114. // Add the end bits
  115. result.push({
  116. data: "010101",
  117. options: {height: this.guardHeight}
  118. });
  119. // Add the UPC-A check digit beneath the quiet zone
  120. if(this.displayValue){
  121. result.push({
  122. data: "00000000",
  123. text: this.text[7],
  124. options: {textAlign: "right", fontSize: this.fontSize}
  125. });
  126. }
  127. return result;
  128. }
  129. encodeMiddleDigits() {
  130. const numberSystem = this.upcA[0];
  131. const checkDigit = this.upcA[this.upcA.length - 1];
  132. const parity = PARITIES[parseInt(checkDigit)][parseInt(numberSystem)];
  133. return encode(this.middleDigits, parity);
  134. }
  135. }
  136. function expandToUPCA(middleDigits, numberSystem) {
  137. const lastUpcE = parseInt(middleDigits[middleDigits.length - 1]);
  138. const expansion = EXPANSIONS[lastUpcE];
  139. let result = "";
  140. let digitIndex = 0;
  141. for(let i = 0; i < expansion.length; i++) {
  142. let c = expansion[i];
  143. if (c === 'X') {
  144. result += middleDigits[digitIndex++];
  145. } else {
  146. result += c;
  147. }
  148. }
  149. result = `${numberSystem}${result}`;
  150. return `${result}${checksum(result)}`;
  151. }
  152. export default UPCE;