I've found a Javascript library that can parse HIBC barcodes - I'm new to Javascript and stuck with getting started and calling the decode function with a barcode parameter to have it decoded and return the result.
I imagine I need to do something like this:
var myString = '+A123BJC5D6E71G';
var result = decode (myString);
but I'm stuck getting this to run and return a result of the decode function.
/*
HIBC Decoder
decode(barcode)
isMatch(decodedLine1, decodedLine2)
errors
type
*/
(function () {
var error = {
BarcodeNotAString: 1,
EmptyBarcode: 2,
BarcodeNotHIBC: 3,
InvalidBarcode: 4,
InvalidDate: 5,
EmptyCheckCharacter: 6,
EmptyLinkCharacter: 7,
InvalidQuantity: 8,
InvalidLine1: 9
};
var type = {
Concatenated: 1,
Line1: 2,
Line2: 3
};
function decode(barcode) {
var decoded = {
barcode: _.clone(barcode)
};
if (!_.isString(barcode)) {
decoded.error = error.BarcodeNotAString;
return decoded;
}
// remove leading *
if (barcode.charAt(0) === "*") {
barcode = barcode.substring(1);
if (_.isEmpty(barcode)) {
decoded.error = error.EmptyBarcode;
return decoded;
}
}
// remove trailing *
if (barcode.charAt(barcode.length - 1) === "*") {
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.EmptyBarcode;
return decoded;
}
}
// Check for + character
if (barcode.charAt(0) !== "+") {
decoded.error = error.BarcodeNotHIBC;
return decoded;
} else {
barcode = barcode.substring(1);
}
// minimum barcode length
if (barcode.length < 4) {
decoded.error = error.InvalidBarcode;
return decoded;
}
// Check and Link characters can contain a "/" so remove them to not affect the split
var potentialCheckAndLinkCharacters = barcode.substring(barcode.length - 2);
barcode = barcode.substring(0, barcode.length - 2);
var array = barcode.split("/");
if (array.length === 1) {
if (matchesLetters(array[0].charAt(0))) {
decoded = processLine1(decoded, type.Line1, array[0] + potentialCheckAndLinkCharacters);
} else {
decoded = processLine2(decoded, type.Line2, array[0] + potentialCheckAndLinkCharacters);
}
return decoded;
} else if (array.length == 2) {
decoded = processLine1(decoded, type.Concatenated, array[0]);
angular.extend(decoded, processLine2({}, type.Concatenated, array[1] + potentialCheckAndLinkCharacters));
return decoded;
} else {
decoded.error = error.InvalidBarcode;
return decoded;
}
}
function processLine1(decoded, t, barcode) {
decoded.type = t;
if (barcode.length < 4) {
decoded.error = error.InvalidLine1;
return decoded;
}
decoded.labelerId = barcode.substring(0, 4);
barcode = barcode.substring(4);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
// if Concatenated the check char is in the second part of the barcode
if (decoded.type !== type.Concatenated) {
decoded.check = barcode.charAt(barcode.length - 1);
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
}
decoded.uom = parseInt(barcode.charAt(barcode.length - 1), 10);
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
decoded.product = barcode;
return decoded;
}
function processLine2(decoded, type, barcode) {
decoded.type = type;
if (barcode.length > 0 && !isNaN(barcode.charAt(0))) {
if (barcode.length < 5) {
decoded.error = error.InvalidDate;
return decoded;
}
decoded.date = moment(barcode.substring(0, 5), "YYDDD");
angular.extend(decoded, decodeLotSerialCheckLink(barcode.substring(5), type, "lot"));
} else if (barcode.length > 2 && barcode.charAt(0) === "$" && !isNaN(barcode.charAt(1))) {
angular.extend(decoded, decodeLotSerialCheckLink(barcode.substring(1), type, "lot"));
} else if (barcode.length > 3 && barcode.substring(0, 2) === "$+" && !isNaN(barcode.charAt(2))) {
angular.extend(decoded, decodeLotSerialCheckLink(barcode.substring(2), type, "serial"));
} else if (barcode.length > 3 && barcode.substring(0, 2) === "$$" && !isNaN(barcode.charAt(2))) {
angular.extend(decoded, decodeLotSerialCheckLink(barcode.substring(2), type, "lot"));
if (!decoded.error) {
extractMomentFromString(decoded, "lot", "date");
}
} else if (barcode.length > 3 && barcode.substring(0, 3) === "$$+") {
angular.extend(decoded, decodeLotSerialCheckLink(barcode.substring(3), type, "serial"));
extractMomentFromString(decoded, "serial", "date");
} else {
decoded.error = error.InvalidBarcode;
}
return decoded;
}
function decodeLotSerialCheckLink(string, barcodeType, propertyName) {
if (_.isEmpty(string)) {
return {
error: error.EmptyCheckCharacter
};
}
var decoded = {};
decoded.lot = string;
string = extractQuantityFromString(decoded, string, "quantity");
// Check character
decoded.check = string.substring(string.length - 1);
string = string.substring(0, string.length - 1);
// LotOrSerial and LinkCharacter
if (barcodeType === type.Line2) {
if (_.isEmpty(string)) {
return {
error: error.EmptyLinkCharacter
};
}
decoded.link = string.substring(string.length - 1);
decoded[propertyName] = string.substring(0, string.length - 1);
} else {
decoded[propertyName] = string;
}
return decoded;
}
function extractMomentFromString(object, stringProperty, momentProperty) {
var string = object[stringProperty];
if (!_.isString(string) || _.isEmpty(string)) {
return;
}
var hibcDateFormat = parseInt(string.substring(0, 1), 10);
if (!_.isNumber(hibcDateFormat)) {
object["error"] = error.InvalidDate;
return;
}
var dateFormat;
switch (hibcDateFormat) {
case 0:
case 1:
dateFormat = "MMYY";
break;
case 2:
dateFormat = "MMDDYY";
break;
case 3:
dateFormat = "YYMMDD";
break;
case 4:
dateFormat = "YYMMDDHH";
break;
case 5:
dateFormat = "YYDDD";
break;
case 6:
dateFormat = "YYDDDHH";
break;
case 7:
// no date following the 7
object[stringProperty] = string.substring(1);
return;
default:
// no date char
return;
}
if (hibcDateFormat > 1) {
string = string.substring(1);
}
if (string.length < dateFormat.length) {
object["error"] = error.InvalidDate;
return;
}
object[momentProperty] = moment(string.substring(0, dateFormat.length), dateFormat);
object[stringProperty] = string.substring(dateFormat.length);
}
function extractQuantityFromString(object, string, quantityProperty) {
var i = parseInt(string.charAt(0), 10);
if (!_.isNumber(i)) {
return string;
}
var length;
switch (i) {
case 8:
length = 2;
break;
case 9:
length = 5;
break;
default:
// no qty
return string;
}
string = string.substring(1);
var quantity = parseInt(string.substring(0, length), 10);
string = string.substring(length);
if (!_.isNumber(quantity)) {
object["error"] = error.InvalidQuantity;
return string;
}
object[quantityProperty] = quantity;
return string;
}
function isMatch(line1, line2) {
if (!_.isObject(line1) || line1.type !== type.Line1 || !_.isObject(line2) || line2.type !== type.Line2) {
return false;
}
return line1.check === line2.link;
}
function matchesLetters(character) {
var letters = /^[a-zA-Z]+$/;
return character.match(letters);
}
function matchesNumbers(character) {
var numbers = /^[0-9]+$/;
return character.match(numbers);
}
/*
Expose hibc
*/
this["HIBC"] = {
decode: decode,
isMatch: isMatch,
type: type,
errors: error
};
}).call(this);
Uff, this is rough. The hibc.js depends on lodash, moment and angular.extend, which have to be available in the global scope. If it is not an Angular project, you can mock the dependency.
In node, this works for me (file has to be a module file, i.e. test.mjs, install requirements with npm i lodash moment):
import hibc from './hibc.js' // local copy of hibc.js
import _ from 'lodash'
import moment from 'moment'
// put requirements into global scope
global._ = _
global.moment = moment
global.angular = {extend: _.extend}
console.log(hibc.HIBC.decode("*+Z999009993020351/05271C"))
Output is:
{
barcode: '*+Z999009993020351/05271C',
type: 1,
labelerId: 'Z999',
uom: 1,
product: '00999302035',
date: Moment<2005-09-28T00:00:00+02:00>,
lot: '',
check: 'C'
}
In the browser, it is a bit easier, since libraries are always imported into global scope:
<script src="file:///home/bl1rt/Public/repos/hbic/hibc.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>
window.angular = {extend: _.extend}
console.log(HIBC.decode("*+Z999009993020351/05271C"))
</script>
But both is pretty gnarly. If I were you, I would update the local copy of hibc.js to make it work in your environment:
replace angular.extend() with lodash's _.extend()
maybe replace the lodash function altogether with builtins
if you want to use it in node, add the imports into the file and turn the iife into an export:
import _ from 'lodash'
import moment from 'moment'
/*
HIBC Decoder
decode(barcode)
isMatch(decodedLine1, decodedLine2)
errors
type
*/
var error = {
BarcodeNotAString: 1,
EmptyBarcode: 2,
BarcodeNotHIBC: 3,
InvalidBarcode: 4,
InvalidDate: 5,
EmptyCheckCharacter: 6,
EmptyLinkCharacter: 7,
InvalidQuantity: 8,
InvalidLine1: 9
};
var type = {
Concatenated: 1,
Line1: 2,
Line2: 3
};
function decode(barcode) {
var decoded = {
barcode: _.clone(barcode)
};
if (!_.isString(barcode)) {
decoded.error = error.BarcodeNotAString;
return decoded;
}
// remove leading *
if (barcode.charAt(0) === "*") {
barcode = barcode.substring(1);
if (_.isEmpty(barcode)) {
decoded.error = error.EmptyBarcode;
return decoded;
}
}
// remove trailing *
if (barcode.charAt(barcode.length - 1) === "*") {
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.EmptyBarcode;
return decoded;
}
}
// Check for + character
if (barcode.charAt(0) !== "+") {
decoded.error = error.BarcodeNotHIBC;
return decoded;
} else {
barcode = barcode.substring(1);
}
// minimum barcode length
if (barcode.length < 4) {
decoded.error = error.InvalidBarcode;
return decoded;
}
// Check and Link characters can contain a "/" so remove them to not affect the split
var potentialCheckAndLinkCharacters = barcode.substring(barcode.length - 2);
barcode = barcode.substring(0, barcode.length - 2);
var array = barcode.split("/");
if (array.length === 1) {
if (matchesLetters(array[0].charAt(0))) {
decoded = processLine1(decoded, type.Line1, array[0] + potentialCheckAndLinkCharacters);
} else {
decoded = processLine2(decoded, type.Line2, array[0] + potentialCheckAndLinkCharacters);
}
return decoded;
} else if (array.length == 2) {
decoded = processLine1(decoded, type.Concatenated, array[0]);
_.extend(decoded, processLine2({}, type.Concatenated, array[1] + potentialCheckAndLinkCharacters));
return decoded;
} else {
decoded.error = error.InvalidBarcode;
return decoded;
}
}
function processLine1(decoded, t, barcode) {
decoded.type = t;
if (barcode.length < 4) {
decoded.error = error.InvalidLine1;
return decoded;
}
decoded.labelerId = barcode.substring(0, 4);
barcode = barcode.substring(4);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
// if Concatenated the check char is in the second part of the barcode
if (decoded.type !== type.Concatenated) {
decoded.check = barcode.charAt(barcode.length - 1);
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
}
decoded.uom = parseInt(barcode.charAt(barcode.length - 1), 10);
barcode = barcode.substring(0, barcode.length - 1);
if (_.isEmpty(barcode)) {
decoded.error = error.InvalidLine1;
return decoded;
}
decoded.product = barcode;
return decoded;
}
function processLine2(decoded, type, barcode) {
decoded.type = type;
if (barcode.length > 0 && !isNaN(barcode.charAt(0))) {
if (barcode.length < 5) {
decoded.error = error.InvalidDate;
return decoded;
}
decoded.date = moment(barcode.substring(0, 5), "YYDDD");
_.extend(decoded, decodeLotSerialCheckLink(barcode.substring(5), type, "lot"));
} else if (barcode.length > 2 && barcode.charAt(0) === "$" && !isNaN(barcode.charAt(1))) {
_.extend(decoded, decodeLotSerialCheckLink(barcode.substring(1), type, "lot"));
} else if (barcode.length > 3 && barcode.substring(0, 2) === "$+" && !isNaN(barcode.charAt(2))) {
_.extend(decoded, decodeLotSerialCheckLink(barcode.substring(2), type, "serial"));
} else if (barcode.length > 3 && barcode.substring(0, 2) === "$$" && !isNaN(barcode.charAt(2))) {
_.extend(decoded, decodeLotSerialCheckLink(barcode.substring(2), type, "lot"));
if (!decoded.error) {
extractMomentFromString(decoded, "lot", "date");
}
} else if (barcode.length > 3 && barcode.substring(0, 3) === "$$+") {
_.extend(decoded, decodeLotSerialCheckLink(barcode.substring(3), type, "serial"));
extractMomentFromString(decoded, "serial", "date");
} else {
decoded.error = error.InvalidBarcode;
}
return decoded;
}
function decodeLotSerialCheckLink(string, barcodeType, propertyName) {
if (_.isEmpty(string)) {
return {
error: error.EmptyCheckCharacter
};
}
var decoded = {};
decoded.lot = string;
string = extractQuantityFromString(decoded, string, "quantity");
// Check character
decoded.check = string.substring(string.length - 1);
string = string.substring(0, string.length - 1);
// LotOrSerial and LinkCharacter
if (barcodeType === type.Line2) {
if (_.isEmpty(string)) {
return {
error: error.EmptyLinkCharacter
};
}
decoded.link = string.substring(string.length - 1);
decoded[propertyName] = string.substring(0, string.length - 1);
} else {
decoded[propertyName] = string;
}
return decoded;
}
function extractMomentFromString(object, stringProperty, momentProperty) {
var string = object[stringProperty];
if (!_.isString(string) || _.isEmpty(string)) {
return;
}
var hibcDateFormat = parseInt(string.substring(0, 1), 10);
if (!_.isNumber(hibcDateFormat)) {
object["error"] = error.InvalidDate;
return;
}
var dateFormat;
switch (hibcDateFormat) {
case 0:
case 1:
dateFormat = "MMYY";
break;
case 2:
dateFormat = "MMDDYY";
break;
case 3:
dateFormat = "YYMMDD";
break;
case 4:
dateFormat = "YYMMDDHH";
break;
case 5:
dateFormat = "YYDDD";
break;
case 6:
dateFormat = "YYDDDHH";
break;
case 7:
// no date following the 7
object[stringProperty] = string.substring(1);
return;
default:
// no date char
return;
}
if (hibcDateFormat > 1) {
string = string.substring(1);
}
if (string.length < dateFormat.length) {
object["error"] = error.InvalidDate;
return;
}
object[momentProperty] = moment(string.substring(0, dateFormat.length), dateFormat);
object[stringProperty] = string.substring(dateFormat.length);
}
function extractQuantityFromString(object, string, quantityProperty) {
var i = parseInt(string.charAt(0), 10);
if (!_.isNumber(i)) {
return string;
}
var length;
switch (i) {
case 8:
length = 2;
break;
case 9:
length = 5;
break;
default:
// no qty
return string;
}
string = string.substring(1);
var quantity = parseInt(string.substring(0, length), 10);
string = string.substring(length);
if (!_.isNumber(quantity)) {
object["error"] = error.InvalidQuantity;
return string;
}
object[quantityProperty] = quantity;
return string;
}
function isMatch(line1, line2) {
if (!_.isObject(line1) || line1.type !== type.Line1 || !_.isObject(line2) || line2.type !== type.Line2) {
return false;
}
return line1.check === line2.link;
}
function matchesLetters(character) {
var letters = /^[a-zA-Z]+$/;
return character.match(letters);
}
function matchesNumbers(character) {
var numbers = /^[0-9]+$/;
return character.match(numbers);
}
/*
Expose hibc
*/
export const HIBC = {
decode: decode,
isMatch: isMatch,
type: type,
errors: error
};
Now you can import and use it as:
import {HIBC} from './hibc.mjs'
console.log(HIBC.decode("*+Z999009993020351/05271C"))
(Depending on your setup, you might have to turn it into a module, i.e. hibc.mjs)
Related
I have a string and need to check with and get whether the following strings overlap with the start and end of my target string:
target string: "click on the Run"
search strings: "the Run button to", "code and click on"
Apparently:
"the Run button to" is overlapped at the end of target "click on the Run"
"code and click on" is overlapped at the start of target "click on the Run"
Both, "the Run" and "click on" will be the desired results.
I have come up with a function to check and get the overlapped results for the cases at the start and at the end separately.
Question:
But my code could not be able to get the expected results only if I know how the search string overlapped with the target string in the very first place. And how can I combine the searched results in one go as well?
function findOverlapAtEnd(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1));
}
function findOverlapAtStart(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1));
}
console.log(findOverlapAtEnd("click on the Run", "the Run button to"))
console.log(findOverlapAtStart("click on the Run", "code and click on"))
edited:
case in the middle is also considered, e.g.:
target string: "click on the Run"
search strings: "on the"
Return value: "on the"
You may try this
function findOverlapAtEnd(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1), min);
}
function findOverlapAtStart(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1), min);
}
const GetOverlappingSection = (target, search, min) => {
if (target.length < search.length) {
const tmp = target;
target = search;
search = tmp;
}
let overlap1 = findOverlapAtStart(target, search, min);
if (overlap1.length === 0) {
overlap1 = findOverlapAtEnd(target, search, min);
}
return overlap1;
};
const removeEmptyKeyword = overlap => {
let tmpFinaloverlap = [];
overlap.forEach((key, idx) => {
if (!(key.trim().length === 0)) {
tmpFinaloverlap = [...tmpFinaloverlap, key];
}
});
return tmpFinaloverlap;
};
// let overlap = ['click on','the Run']
const GetOverlappingOfKeyowrd1And2 = (keywordSet1, keywordSet2,min) => {
let resultSetoverlap = [];
let tmpresultSetoverlap = [];
keywordSet1.forEach(key =>
keywordSet2.forEach(k2 => {
tmpresultSetoverlap = [
...tmpresultSetoverlap,
GetOverlappingSection(key, k2, min),
];
})
);
// get the resultSetoverlap
tmpresultSetoverlap.forEach(element => {
if (element.length > 0) {
resultSetoverlap = [...resultSetoverlap, element];
}
});
return resultSetoverlap;
};
const min = 2;
//To handle overlapping issue in overlapping set, that casuing
overlap.forEach((key, idx) => {
if (idx < overlap.length - 1) {
for (let i = idx + 1; i < overlap.length; i++) {
console.log(`key: ${key}`);
console.log(`search: ${overlap[i]}`);
let overlapSection = GetOverlappingSection(key, overlap[i], min);
if (overlapSection.length > 0) {
console.log(`overlapSection: ${overlapSection}`);
overlap[idx] = overlap[idx].replace(overlapSection, '');
}
}
}
});
overlap = removeEmptyKeyword(overlap);
console.log(overlap);
overlap.forEach(key => {
keywordSet2 = keywordSet2.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
overlap.forEach(key => {
keywordSet1 = keywordSet1.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
keywordSet2 = removeEmptyKeyword(keywordSet2);
keywordSet1 = removeEmptyKeyword(keywordSet1);
overlap.forEach(key => {
text = text.replace(key, `$#k1k2$&$`);
});
keywordSet1.forEach(key => {
text = text.replace(key, `$#k1$&$`);
});
keywordSet2.forEach(key => {
text = text.replace(key, `$#k2$&$`);
});
console.log(`ResultSetoverlap after processing:${text}`);
Because I need to decompress and I find these logic puzzles fun, here's my solution to the problem...
https://highdex.net/begin_end_overlap.htm
You can view source of the page to see JavaScript code I used. But just in case I ever take that page down, here's the important function...
function GetOverlappingSection(str1, str2, minOverlapLen = 4) {
var work1 = str1;
var work2 = str2;
var w1Len = work1.length;
var w2Len = work2.length;
var resultStr = "";
var foundResult = false;
var workIndex;
if (minOverlapLen < 1) { minOverlapLen = 1; }
else if (minOverlapLen > (w1Len > w2Len ? w2Len : w1Len)) { minOverlapLen = (w1Len > w2Len ? w2Len : w1Len); }
//debugger;
//we have four loops to go through. We trim each string down from each end and see if it matches either end of the other string.
for (var i1f = 0; i1f < w1Len; i1f++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(1);
if (work1.length < minOverlapLen) { break; }
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i1b = 0; i1b < w1Len; i1b++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(0, work1.length - 1);
if (work1.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i2f = 0; i2f < w2Len; i2f++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(1);
if (work2.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work2 = str2;
for (var i2b = 0; i2b < w2Len; i2b++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(0, work2.length - 1);
if (work2.length < minOverlapLen) { break; }
}
}
return resultStr;
}
Hopefully that's helpful.
I am kind of new to this, but this is giving me a headache.
Heres my code what i am trying to solve:
function parseComponents(data: any, excelAttributesArray: string[]) {
let confs = "";
let isValues = false;
let listValues = "";
if (!data) return confs;
if (data["Part"]) {
const part = data["Part"];
excelAttributesArray.forEach((attribute) => {
let attributeValue = part[attribute];
if (attributeValue !== null) isValues = true;
if (attributeValue !== null && attributeValue.Value) {
attributeValue = attributeValue.Value;
}
listValues += attributeValue + ",";
});
const number = part["Number"];
if (isValues) {
confs += `${listValues}${number}`;
}
}
if (data["Components"] && data["Components"].length > 0) {
for (let i = 0; i < data["Components"].length; i++) {
const tmp = parseComponents(
data["Components"][i],
excelAttributesArray
);
if (tmp && tmp.length > 0)
confs += (confs.length > 0 ? "|" : "") + tmp;
}
}
return confs;
}
The confs value is returned as a string. How do i get it return as array?
I am given an "array" with JSON Objects inside like so (it's not an actual array since it begins with curly braces):
{{"x1","x2"},{"y1","y2"},{"z1","z2"}}
How can I make it so that the first and last { curly braces } becomes square braces [ ]?
Javascript does not recognize the above example as an array and throws an error. Calling JSON.stringify or JSON.parse does not work either since the above is not actual JSON/Array. Only when it has [ square brackets ] does it actually work since then it is an array with JSON objects inside it. Like so:
[{"x1","x2"},{"y1","y2"},{"z1","z2"}]
I was thinking of making it into a string first, then replacing the first and last char with [ and ] respectively, but calling String(value), where value is the first "array", simply doesn't cut it as it thinks it is a JSON and throws unexpected token if I even declare it.
If you're trying to create an array of JSON objects, you could do as follow:
const object = new Array(
{ 'x1': 'x2' },
{ 'y1': 'y2' },
{ 'z1': 'z2' }
);
console.log( object[0] );
expecting in the console the following result:
{
x1: "x2"
}
Hope it helps.
As it was already pointed out in comments, your input JSON isn't really JSON at all - you'll want a custom parser for it. Here's something quickly scrambled from Haxe's haxe.format.JsonParser:
var Std = function() { };
Std.parseInt = function(x) {
if(x != null) {
var _g = 0;
var _g1 = x.length;
while(_g < _g1) {
var i = _g++;
var c = x.charCodeAt(i);
if(c <= 8 || c >= 14 && c != 32 && c != 45) {
var nc = x.charCodeAt(i + 1);
var v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);
if(isNaN(v)) {
return null;
} else {
return v;
}
}
}
}
return null;
};
var StringBuf = function() {
this.b = "";
};
var JsonParser = function(str) {
this.str = str;
this.pos = 0;
};
JsonParser.prototype = {
doParse: function() {
var result = this.parseRec();
var c;
while(true) {
c = this.str.charCodeAt(this.pos++);
if(!(c == c)) {
break;
}
switch(c) {
case 9:case 10:case 13:case 32:
break;
default:
this.invalidChar();
}
}
return result;
}
,parseRec: function() {
while(true) switch(this.str.charCodeAt(this.pos++)) {
case 9:case 10:case 13:case 32:
break;
case 34:
return this.parseString();
case 123:
var arr = [];
var comma = null;
while(true) switch(this.str.charCodeAt(this.pos++)) {
case 9:case 10:case 13:case 32:
break;
case 44:
if(comma) {
comma = false;
} else {
this.invalidChar();
}
break;
case 125:
if(comma == false) {
this.invalidChar();
}
return arr;
default:
if(comma) {
this.invalidChar();
}
this.pos--;
arr.push(this.parseRec());
comma = true;
}
break;
default:
this.invalidChar();
}
}
,parseString: function() {
var start = this.pos;
var buf = null;
var prev = -1;
while(true) {
var c = this.str.charCodeAt(this.pos++);
if(c == 34) {
break;
}
if(c == 92) {
if(buf == null) {
buf = new StringBuf();
}
var s = this.str;
var len = this.pos - start - 1;
buf.b += len == null ? s.substr(start) : s.substr(start,len);
c = this.str.charCodeAt(this.pos++);
if(c != 117 && prev != -1) {
buf.b += String.fromCodePoint(65533);
prev = -1;
}
switch(c) {
case 34:case 47:case 92:
buf.b += String.fromCodePoint(c);
break;
case 98:
buf.b += String.fromCodePoint(8);
break;
case 102:
buf.b += String.fromCodePoint(12);
break;
case 110:
buf.b += String.fromCodePoint(10);
break;
case 114:
buf.b += String.fromCodePoint(13);
break;
case 116:
buf.b += String.fromCodePoint(9);
break;
case 117:
var uc = Std.parseInt("0x" + this.str.substr(this.pos,4));
this.pos += 4;
if(prev != -1) {
if(uc < 56320 || uc > 57343) {
buf.b += String.fromCodePoint(65533);
prev = -1;
} else {
buf.b += String.fromCodePoint(((prev - 55296 << 10) + (uc - 56320) + 65536));
prev = -1;
}
} else if(uc >= 55296 && uc <= 56319) {
prev = uc;
} else {
buf.b += String.fromCodePoint(uc);
}
break;
default:
throw new ("Invalid escape sequence \\" + String.fromCodePoint(c) + " at position " + (this.pos - 1));
}
start = this.pos;
} else if(c != c) {
throw new ("Unclosed string");
}
}
if(prev != -1) {
buf.b += String.fromCodePoint(65533);
prev = -1;
}
if(buf == null) {
return this.str.substr(start,this.pos - start - 1);
} else {
var s1 = this.str;
var len1 = this.pos - start - 1;
buf.b += len1 == null ? s1.substr(start) : s1.substr(start,len1);
return buf.b;
}
}
,invalidChar: function() {
this.pos--;
throw "Invalid char " + this.str.charCodeAt(this.pos) + " at position " + this.pos;
}
};
JsonParser.parse = function(s) {
return new JsonParser(s).doParse();
}
If someone is giving you this you really ought to go back to the source and inform them that they are NOT providing you with a valid input.
I avoid having to hack around poor source data.
Fix it at the source and not have to deal with it everywhere that it is used.
Problem
If I am selecting lesser than 12 date then it display in this format MM/D/YYYY and if the date is greater than 12 then output comes as DD/M/YYYY. I want to get this format DD/M/YYYY whatever the user select. I am also using protoype.js with it. Any help will be much appreciated.
Code
var Recurrence = Class.create({
// takes a JSON object with pattern options
initialize: function (pattern, date_format) {
if (typeof pattern != 'object') throw new TypeError('pattern must be a JSON');
if (!pattern.every || pattern.every.blank()) {
throw new ReferenceError('Every magnitude must be specified');
}
if (isNaN(parseInt(pattern.every))) {
throw new TypeError('Every magnitude must be a valid number');
}
// stores generated dates based on recurrence pattern
this.dates = [];
this.start = Date.parse(pattern.start);
this.every = parseInt(pattern.every);
this.unit = pattern.unit;
this.end_condition = pattern.end_condition;
this.until = Date.parse(pattern.until);
this.rfor = parseInt(pattern.rfor);
this.occurrence_of = pattern.occurrence_of;
this.nth = parseInt(pattern.nth);
this.radioSelection = pattern.radioSelection;
this.indefinate = Date.parse(pattern.indefinate);
this.days = (pattern.days) ? pattern.days.sort() : [];
this.date_format = date_format || 'dd/M/yyyy';
this.month_date_format = date_format || 'dd';
},
// tries to describe the pattern in plain english
describe: function () {
var units = {'d': 'day', 'w': 'week', 'm': 'month', 'y': 'year'};
var week = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'day'];
var nthword = ['', 'first', 'second', 'third', 'fourth', 'fifth', 'last']
var t = ['Every'];
if (this.every > 2) {
t.push(this.every, units[this.unit] + 's');
} else if (this.every == 2) {
t.push('other', units[this.unit]);
} else {
t.push(units[this.unit]);
}
//alert(this.radioSelection);
//alert(this.end_condition);
if (this.unit == 'w') {
var d = [];
for (var i = 0; i < this.days.length; i++) {
d.push(week[this.days[i]]);
}
t.push('on', d.join(', '));
} else if (this.unit == 'm') {
// check if it's a special word
day_idx = (this.occurrence_of < 0) ? week.length - 1 : this.occurrence_of;
nth_idx = (this.nth < 0) ? nthword.length-1 : this.nth;
//alert(this.radioSelection);
if(this.radioSelection == 'weekday'){
t.push('on the', nthword[nth_idx], week[day_idx]);
}else{
t.push('on date ', this.start.toString(this.month_date_format));
}//end if..
}
t.push('starting on', this.start.toString(this.date_format));
if (this.end_condition == 'until') {
t.push('until', this.until.toString(this.date_format));
} else if (this.end_condition == 'for') {
t.push('for', this.rfor, 'occurrences');
} else if(this.end_condition == 'indefinate'){
t.push('ends never.');//alert('sds');
}
return t.join(' ');
},
// determine whether given date is in recurrence
contains: function (d) {
if (this.dates.length == 0) this.generate();
// can be string or date object already
d = Date.parse(d);
for (var i = 0; i < this.dates.length; i++) {
if (Date.equals(this.dates[i], d)) return true;
}
return false;
},
// returns an array of dates base on input pattern
generate: function (max) {
if (!(this.rfor || this.until || max)) {
throw new RangeError('There is no valid end condition specified');
}
var end_condition_reached = function (occurrences, current_date) {
if (max && occurrences.length >= max) return true;
if (this.end_condition == 'for' && this.rfor && occurrences.length >= this.rfor) return true;
if (this.end_condition == 'until' && this.until && current_date > this.until) return true;
if (this.end_condition == 'indefinate' && this.indefinate && current_date > this.indefinate) return true;
return false;
}.bind(this);
var dates = [];
var curr = this.start.clone().clearTime();
// always include start date in recurrence
dates.push(curr.clone());
// weekly recurrence
if (this.unit == 'w') {
// if it's not already a sunday, move it to the current week's sunday
if (!curr.is().sunday()) curr.last().sunday();
if (this.days.length == 0) {
throw new RangeError('Weekly recurrence was selected without any days specified.');
return null;
}
while (!end_condition_reached(dates, curr)) {
// scan through the checked days
this.days.each(function (d) {
if (curr.getDay() < d) curr.moveToDayOfWeek(d);
if (curr <= this.start) return;
if (end_condition_reached(dates, curr)) return;
dates.push(curr.clone());
}.bind(this));
// rewind back to sunday
if (!curr.is().sunday()) curr.last().sunday();
// next repetition
curr.addWeeks(this.every);
}
} else if (this.unit == 'm') {
while (true) {
if (this.occurrence_of == -1) {
curr.moveToLastDayOfMonth();
} else {
if(this.radioSelection == 'weekday'){
curr.moveToNthOccurrence(this.occurrence_of, this.nth);
}else{
//this.occurrence_of = this.faltu_date;
}//end if
}//end if..
if (end_condition_reached(dates, curr)) break;
if (curr > this.start) {
dates.push(curr.clone());
}//end if..
curr.addMonths(this.every);
}//end while..
} else {
while (true) {
if (this.unit == 'd') {
curr.addDays(this.every);
} else if (this.unit == 'y') {
curr.addYears(this.every);
}
// else infinite loop yay
if (end_condition_reached(dates, curr)) break;
dates.push(curr.clone());
}
}
// cache results
this.dates = dates;
return this.dates;
}
});
How to add a Visual Basic .NET syntax highlighting to CodeMirror editor? Does exists the mode for this language on any library? What should I correct except keywords, blockKeywords and atoms?
Pascal example:
CodeMirror.defineMode("pascal", function(config) {
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var keywords = words("and array begin case const div do downto else end file for forward integer " +
"boolean char function goto if in label mod nil not of or packed procedure " +
"program record repeat set string then to type until var while with");
var blockKeywords = words("case do else for if switch while struct then of");
var atoms = {"null": true};
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
var curPunc;
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == "#" && state.startOfLine) {
stream.skipToEnd();
return "meta";
}
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (ch == "(" && stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return null
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
if (ch == "/") {
if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
}
if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return "operator";
}
stream.eatWhile(/[\w\$_]/);
var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
return "keyword";
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
return "word";
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {end = true; break;}
escaped = !escaped && next == "\\";
}
if (end || !escaped) state.tokenize = null;
return "string";
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == ")" && maybeEnd) {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" )
state.indented = state.context.indented;
return state.context = state.context.prev;
}
// Interface
return {
startState: function(basecolumn) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
indented: 0,
startOfLine: true
};
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
curPunc = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == ctx.type) popContext(state);
else if ( ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
return style;
},
electricChars: "{}"
};
});
CodeMirror.defineMIME("text/x-pascal", "pascal");
Thanks for the help!
This worked for me -
I added this definition in clike mode js file
CodeMirror.defineMIME("text/x-vb", {
name: "clike",
keywords: words("AddHandler AddressOf Alias And AndAlso Ansi As Assembly Auto Boolean ByRef Byte " +
"ByVal Call Case Catch CBool CByte CChar CDate CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType " +
"Date Decimal Declare Default Delegate Dim DirectCast Do Double Each Else ElseIf End Enum Erase Error Event Exit False Finally "+
"For Friend Function Get GetType GoSub GoTo Handles If Implements Imports In Inherits Integer Interface Is " +
"Let Lib Like Long Loop Me Mod Module MustInherit MustOverride MyBase MyClass Namespace New Next Not "+
"Nothing NotInheritable NotOverridable Object On Option Optional Or OrElse Overloads Overridable Overrides " +
"ParamArray Preserve Private Property Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler Resume " +
"Return Select Set Shadows Shared Short Single Static Step Stop String Structure Sub SyncLock Then Throw " +
"To True Try TypeOf Unicode Until Variant When While With WithEvents WriteOnly Xor"),
//blockKeywords: words("catch class do else finally for if switch try while"),
atoms: words("True False Null"),
hooks: {
"#": function(stream, state) {
stream.eatWhile(/[\w\$_]/);
return "meta";
}
}
});