Extract Font Name from PDF - javascript

I am using pdf.js to extract text from the pdf but the font name appears as g_d0_f6 etc. I need the font name to use the appropriate table for converting to Unicode. Here is the code derived from pdf2svg.js sample:-
var fs = require('fs');
var util = require('util');
var path = require('path');
var stream = require('stream');
// HACK few hacks to let PDF.js be loaded not as a module in global space.
require('./domstubs.js').setStubs(global);
var pdfjsLib = require('pdfjs-dist');
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
var data = new Uint8Array(fs.readFileSync(pdfPath));
var loadingTask = pdfjsLib.getDocument({
data: data,
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
});
loadingTask.promise.then(function(doc) {
var lastPromise = Promise.resolve(); // will be used to chain promises
var loadPage = function (pageNum) {
return doc.getPage(pageNum).then(function (page) {
return page.getTextContent().then(function (textContent) {
console.log(textContent);
});
});
};
for (var i = 1; i <= doc.numPages; i++) {
lastPromise = lastPromise.then(loadPage.bind(null, i));
}
return lastPromise;
}).then(function () {
console.log('# End of Document');
}, function (err) {
console.error('Error: ' + err);
});
Sample output:-
{ items:
[ { str: 'bl fp=k osQ ckjs esa cPpksa ls ckrphr djsa & ;g LowQy esa fdl le; dk n`\'; gS\\ cPps',
dir: 'ltr',
width: 396.2250000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'D;k dj jgs gSa\\ cPps dkSu&dkSu ls [ksy] [ksy j',
dir: 'ltr',
width: 216.1650000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'g',
dir: 'ltr',
width: 6.42,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 's gSa\\ fp=k esa fdrus cPps gSa vkSj fdrus',
dir: 'ltr',
width: 173.865,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'cM+s gSa\\ vkil esa dkSu D;k ckr dj jgk gksxk\\ cPpksa ls fp=k esa lcosQ fy, uke lkspus',
dir: 'ltr',
width: 396.54000000000013,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'dks dgasaA',
dir: 'ltr',
width: 40.74,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'csVh cpkvks',
dir: 'ltr',
width: 66.725,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: 'csVh i<+kvksA',
dir: 'ltr',
width: 66.75899999999999,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: '2018-19',
dir: 'ltr',
width: 36.690000000000005,
height: 10,
transform: [Array],
fontName: 'g_d0_f3' } ],
styles:
{ g_d0_f1:
{ fontFamily: 'sans-serif',
ascent: 0.837,
descent: -0.216,
vertical: false },
g_d0_f2:
{ fontFamily: 'sans-serif',
ascent: 0.786,
descent: -0.181,
vertical: false },
g_d0_f3:
{ fontFamily: 'sans-serif',
ascent: 0.9052734375,
descent: -0.2119140625,
vertical: false } } }
And here is the pdf that uses embedded fonts: http://ncert.nic.in/textbook/pdf/ahhn101.pdf
Here is a related question but the suggested commonObjs is empty: pdf.js get info about embedded fonts

Note: The answer below does not have anything to do with pdf.js, however it answers the question, Extract Font Name from PDF.
I did not find a solution yet, so I went ahead and grabbed mutool, which has has the following command to get the font information per page.
mutool info -F input.pdf 0-2147483647
Then I grabbed the spawn function, hacked the output through some regex and pattern matching to return the data.
const extractFontData = async str => {
const getMatches = str => {
const regex = /Page (\d+):\nFonts \((\d+)\):/;
const match = str.match(regex);
if (match) {
return { page: match[1], fonts: match[2] };
}
return {};
};
const singleFont = fontData => {
const match = fontData.match(/\+([a-zA-Z0-9_-]+[.,]?[a-zA-Z0-9_-]+)/);
return match && match[1];
};
return str
.split("Page ")
.map(singlePageData => {
const { page, fonts } = getMatches(`Page ` + singlePageData);
if (fonts) {
const split = singlePageData.split("\n").filter(e => e.length);
const fontList = split.slice(2).map(singleFont);
return { page, fonts, fontList };
}
})
.filter(e => e);
};
// Taken and adjusted from: https://stackoverflow.com/a/52611536/6161265
function run(...cmd) {
return new Promise((resolve, reject) => {
var { spawn } = require("child_process");
var command = spawn(...cmd);
var result = "";
command.stdout.on("data", function(data) {
result += data.toString();
});
command.on("close", function(code) {
resolve(result);
});
command.on("error", function(err) {
reject(err);
});
});
}
async function wrapper(filePath) {
const data = await run("mutool", ["info", "-F", filePath, "0-2147483647"]);
return extractFontData(data);
}
Sample usage:
wrapper("ahhn101.pdf").then(data => console.log(data));
Result:

I think you were on the right track: page.commonObjs is where the actual font name is found. However, page.commonObjs only gets populated when the page's text/operators are accessed, so you'll find it empty if you look before that happens.

Related

How loop images to excel js

i tried loop images from array data into excel using excel js, but the images doesn't show at all.
this this my looping code:
async testAja() {
const workbook = new excelJS.Workbook();
const worksheet = workbook.addWorksheet("My Sheet");
worksheet.columns = [
{ header: 'Date', key: 'date', width: 15, style: { numFmt: 'dd/mm/yyyy' } },
{ header: 'Title', key: 'title', width: 100 },
{ header: 'Confirmation', key: 'confirmation', width: 15 },
{ header: 'Location', key: 'location', width: 15 },
{ header: 'Remark', key: 'remark', width: 15 },
{ header: 'Photo', key: 'photo', width: 20 },
];
let num = 1;
this.state.dataInspection.forEach(async (val, idx) => {
if (val.label_id === null && val.label_id === '') {
const imageBuffer = await axios.get(`https://toqrikyppyhsmwwiabyc.supabase.co/storage/v1/object/public/inspection/photos/${val.photo}`, { responseType: 'arraybuffer' });
const imageId = workbook.addImage({
buffer: imageBuffer.data,
});
worksheet.addImage(imageId, `A${num + 1}:A${num + 5}`);
num += 1;
}
});
workbook.xlsx.writeBuffer().then(function (buffer) {
const blob = new Blob([buffer], { type: "applicationi/xlsx" });
saveAs(blob, "inspection.xlsx");
});
}
and here is my array data
enter image description here

Sequelize how to get AUTO_INCREMENT next value?

how can I get what will be next auto_increment value using Sequelize?
Using mysql query:
SELECT auto_increment
FROM information_schema.tables
WHERE table_schema = 'skolboz'
AND table_name = "cases";
Response is 7 because last inserted row in Cases is 6.
How can I achieve this using Sequelize? Is it even possible?
Thanks
EDIT:
Here is Sequelize model definition:
module.exports = (sequelize, DataTypes) => {
const Case = sequelize.define('Case', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
caseName: DataTypes.STRING,
constructionSite: DataTypes.STRING,
createdBy: DataTypes.STRING,
dateOfDiscovery: {
type: DataTypes.DATEONLY,
get: function() {
return moment(this.getDataValue('dateOfDiscovery')).format('DD.MM.YYYY')
}},
placeOfDiscovery: DataTypes.STRING,
responsible: DataTypes.STRING,
text: DataTypes.TEXT,
sanction: DataTypes.INTEGER,
forCompany: DataTypes.STRING,
priority: DataTypes.STRING,
isActive: {
type: DataTypes.INTEGER,
defaultValue: 1,
},
wasSended: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
})
Case.associate = (models) => {
Case.hasMany(models.caseimages, {foreignKey: 'id', as: 'images'});
};
return Case
}
Here is controller for creating case and adding photo to it.
async postCaseWithImages(req, res) {
try {
await upload(req, res);
console.log(req.files);
if (req.files.length <= 0) {
return res.send(`Musíte vybrať aspoň 1 fotku`);
}
const uploadsFileNames = [];
const uploadsMimeTypes = [];
const uploadsPath = [];
global.creationDate;
global.koordinatorName;
global.problemName;
global.constructionName;
global.discoveryPlace;
global.responsible;
global.problemText;
global.problemSanction;
global.adressedFor;
global.problemPriority;
global.problemActivity;
global.wasSended;
global.newCaseId;
Case.create({
caseName: req.body.caseName,
constructionSite: req.body.constructionSite,
createdBy: req.body.createdBy,
dateOfDiscovery: req.body.dateOfDiscovery,
placeOfDiscovery: req.body.placeOfDiscovery,
responsible: req.body.responsible,
text: req.body.text,
sanction: req.body.sanction,
forCompany: req.body.forCompany,
priority: req.body.priority,
isActive: req.body.isActive,
})
.then((result) => {
let formatedDate = moment(result.createdAt).format(
"DD.MM.YYYY, HH:mm:ss"
);
creationDate = formatedDate;
koordinatorName = result.createdBy;
problemName = result.caseName;
constructionName = result.constructionSite;
discoveryPlace = result.placeOfDiscovery;
responsible = result.responsible;
problemText = result.text;
problemSanction = result.sanction;
adressedFor = result.forCompany;
problemPriority = result.priority;
problemActivity = result.isActive;
wasSended = result.wasSended;
newCaseId = result.id;
})
.catch((err) => {
console.log(err);
res.status(500).send({
error: "Nepodarilo sa vytvoriť nedostatok z dôvodu: ",
err,
});
})
.then(() => {
const checkId = Case.findOne({ where: {id: newCaseId }});
if (checkId == null) {
res.status(400).send({ message: 'Prípad so zadaným ID sa nenašiel.'});
return;
}
for(let i=0;i<req.files.length;i++){
uploadsFileNames.push(req.files[i].filename);
uploadsMimeTypes.push(req.files[i].mimetype);
uploadsPath.push(req.files[i].destination);
CaseImage.create({
fileName: uploadsFileNames[i],
mimeType: uploadsMimeTypes[i],
caseId: newCaseId,
path: uploadsPath[i],
})
}
let doc = new PDFDocument({ margin: 30, size: "A4", compress:false });
doc.pipe(
fs.createWriteStream(`pdf/${problemName}_${creationDate}` + ".pdf")
);
doc.image('logo.png', 485, 10, {width: 100})
const photosToPdf = [];
let positionX = 30;
let positionY = 240;
for(let j=0;j<uploadsPath.length;j++){
photosToPdf.push(uploadsFileNames[j]);
}
photosToPdf.forEach(img => {
if(positionX == 555){
positionX = 30
positionY = positionY + 160
}
doc.image(`uploads/${img}`, positionX, positionY, {width: 265});
positionX = positionX + 275
});
const table = {
title: "Zápis koordinátora " + koordinatorName + "zo dna " + creationDate + ".",
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Názov", property: 'name', width: 70, renderer: null },
{ label:"Názov staveniska (stavba)", property: 'construction', width: 80, renderer: null },
{ label:"Vytvoril koordinátor BOZP", property: 'createdName', width: 80, renderer: null },
{ label:"Priorita", property: 'priority', width: 50, renderer: null },
{ label:"Dátum zistenia", property: 'date', width: 80, renderer: null },
{ label:"Zodpovedný za vyriešenie zistenia", property: 'responsible', width: 100, renderer: null },
{ label:"Miesto zistenia", property: 'placeOfDiscovery', width: 90, renderer: null },
],
datas: [
{
options: { fontSize: 10, separation: true},
name: problemName,
construction: constructionName,
createdName: koordinatorName,
priority: problemPriority,
date: creationDate,
responsible: responsible,
placeOfDiscovery: discoveryPlace,
},
],
};
doc.table(table, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
const table2 = {
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Návrh na udelenie sankcie", property: 'sanction', width: 100, renderer: null },
{ label:"Pre spolocnost", property: 'forCompany', width: 100, renderer: null },
{ label:"Popis problému", property: 'text', width: 350, renderer: null},
],
datas: [
{
options: { fontSize: 10, separation: true},
sanction: 50,
forCompany: adressedFor,
text: problemText,
},
],
};
doc.table(table2, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
doc.end();
})
.catch((err) => {
console.log(err);
res.status(500)
})
await highPriorityEmail();
res.status(200).send({
message: "Nedostatok bol úspešne vytvorený.",
});
} catch (err) {
console.log(err);
res.status(500);
}
},
Here is route:
app.post('/api/v1/cases/:id/images',
CaseImagesController.postCaseWithImages)
Here is Vue.js function:
async submitCaseWithPhotos() {
const id = this.newId;
const bozpCaseImage = new FormData();
bozpCaseImage.append('multi-files', this.file);
bozpCaseImage.append('caseName', this.caseName);
bozpCaseImage.append('constructionSite', this.$store.state.selectedConstruction);
bozpCaseImage.append('createdBy', this.logedUser);
bozpCaseImage.append('dateOfDiscovery', this.date);
bozpCaseImage.append('responsible', this.responsible);
bozpCaseImage.append('placeOfDiscovery', this.placeOfDiscovery);
bozpCaseImage.append('text', this.text);
bozpCaseImage.append('sanction', this.sanction);
bozpCaseImage.append('forCompany', this.forCompany);
bozpCaseImage.append('priority', this.priority);
CaseImagesService.postImageWithCase(id, bozpCaseImage)
.then((response) => {
console.log(response)
this.$router.push({ name: 'Cases' });
})
.catch((error) => {
console.log(error)
this.error = "Failed to submit data - please try again later.";
});
},
And this is function when I get this.newId:
async getNewCaseId(){
CasesService.index()
.then((response) => {
const resData = response.data;
const responseArray = []
responseArray.push(resData);
const arrayLength = responseArray[0].length;
const lastId = responseArray[0][arrayLength - 1].id
const newId = lastId + 1
console.log(newId);
this.newId = newId;
})
}
Here is working, updated function.
async postCaseWithImages(req, res) {
try {
await upload(req, res);
console.log(req.files);
if (req.files.length <= 0) {
return res.send(`Musíte vybrať aspoň 1 fotku`);
}
const uploadsFileNames = [];
const uploadsMimeTypes = [];
const uploadsPath = [];
global.newCaseId;
global.creationDate;
global.koordinatorName;
global.problemName;
global.constructionName;
global.discoveryPlace;
global.responsible;
global.problemText;
global.problemSanction;
global.adressedFor;
global.problemPriority;
global.problemActivity;
global.wasSended;
global.emailGroup;
Case.create({
caseName: req.body.caseName,
constructionSite: req.body.constructionSite,
createdBy: req.body.createdBy,
dateOfDiscovery: req.body.dateOfDiscovery,
placeOfDiscovery: req.body.placeOfDiscovery,
responsible: req.body.responsible,
text: req.body.text,
sanction: req.body.sanction,
forCompany: req.body.forCompany,
priority: req.body.priority,
isActive: req.body.isActive,
mailingListGroup: req.body.mailingListGroup,
})
.then((result) => {
let formatedDate = moment(result.createdAt).format(
"DD.MM.YYYY, HH:mm:ss"
);
newCaseId = result.id;
creationDate = formatedDate;
koordinatorName = result.createdBy;
problemName = result.caseName;
constructionName = result.constructionSite;
discoveryPlace = result.placeOfDiscovery;
responsible = result.responsible;
problemText = result.text;
problemSanction = result.sanction;
adressedFor = result.forCompany;
problemPriority = result.priority;
problemActivity = result.isActive;
wasSended = result.wasSended;
emailGroup = result.mailingListGroup;
})
.catch(() => {
console.log(err);
res.status(500).send({
error: "Nepodarilo sa vytvoriť nedostatok z dôvodu: ",
err,
});
})
.then(async () => {
const checkId = Case.findOne({ where: {id: newCaseId }});
if (checkId == null) {
res.status(400).send({ message: 'Prípad so zadaným ID sa nenašiel.'});
return;
}
for(let i=0;i<req.files.length;i++){
uploadsFileNames.push(req.files[i].filename);
uploadsMimeTypes.push(req.files[i].mimetype);
uploadsPath.push(req.files[i].destination);
CaseImage.create({
fileName: uploadsFileNames[i],
mimeType: uploadsMimeTypes[i],
caseId: newCaseId,
path: uploadsPath[i],
})
}
let doc = new PDFDocument({ margin: 30, size: "A4", compress:false });
doc.pipe(
fs.createWriteStream(`pdf/${problemName}_${creationDate}` + ".pdf")
);
doc.image('Skolboz_bez_pozadia.png', 500, 25, {width: 100})
const photosToPdf = [];
let positionX = 30;
let positionY = 240;
for(let j=0;j<uploadsPath.length;j++){
photosToPdf.push(uploadsFileNames[j]);
}
photosToPdf.forEach(img => {
if(positionX >= 550){
positionX = 30
positionY = positionY + 215
}
doc.image(`uploads/${img}`, positionX, positionY, {width: 265});
positionX = positionX + 275
});
const table = {
title: "Zápis koordinátora " + koordinatorName + " zo dna " + creationDate + ".",
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Názov", property: 'name', width: 70, renderer: null },
{ label:"Názov staveniska (stavba)", property: 'construction', width: 80, renderer: null },
{ label:"Vytvoril koordinátor BOZP", property: 'createdName', width: 80, renderer: null },
{ label:"Priorita", property: 'priority', width: 50, renderer: null },
{ label:"Dátum zistenia", property: 'date', width: 80, renderer: null },
{ label:"Zodpovedný za vyriešenie zistenia", property: 'responsible', width: 100, renderer: null },
{ label:"Miesto zistenia", property: 'placeOfDiscovery', width: 90, renderer: null },
],
datas: [
{
options: { fontSize: 10, separation: true},
name: problemName,
construction: constructionName,
createdName: koordinatorName,
priority: problemPriority,
date: creationDate,
responsible: responsible,
placeOfDiscovery: discoveryPlace,
},
],
};
doc.table(table, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
const table2 = {
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Návrh na udelenie sankcie", property: 'sanction', width: 100, renderer: null },
{ label:"Pre spolocnost", property: 'forCompany', width: 100, renderer: null },
{ label:"Popis problému", property: 'text', width: 350, renderer: null},
],
datas: [
{
options: { fontSize: 10, separation: true},
sanction: 50,
forCompany: adressedFor,
text: problemText,
},
],
};
doc.table(table2, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
doc.end();
await highPriorityEmail(emailGroup);
})
.catch((err) => {
console.log(err);
res.status(500)
})
.then(() => {
res.status(200).send({
message: "Nedostatok bol úspešne vytvorený.",
});
})
} catch (err) {
console.log(err);
res.status(500);
}
},
Here is also new HighPriorityEmail() function, which now gets parameter.
function highPriorityEmail(emailGroup){
return new Promise((resolve, reject) => {
setTimeout(async () => {
const emailAdress = await getEmails(emailGroup);
let filePath = path.join(__dirname, `../../pdf/${problemName}_${creationDate}.pdf`);
let attachment = fs.readFileSync(filePath).toString("base64");
let fileName = `${problemName}_${creationDate}.pdf`;
if (problemPriority == "vysoká") {
const msg = {
to: emailAdress, // Change to your recipient
from: "someone#example.com"
subject: "Vytvorenie nového nedostatku: " + problemName,
html: `
Dobrý deň, <br>
<br>
dňa ${creationDate} bol vykonaný dozor koordinátora ${koordinatorName}. <br>
Boli zistené nedostatky s vysokou prioritou, ktoré sú priložené v prílohe tohoto emailu.
<br>
`,
attachments: [
{
content: attachment,
filename: fileName,
type:'application/pdf'
},
],
};
sgMail
.send(msg)
.then(() => {
console.log("Email sent");
})
.catch((error) => {
console.error(error);
});
Case.update(
{ wasSended: 1 },
{ returning: true, where: { caseName: problemName } }
);
}
resolve();
}, 1000)
});
};
And finally here is getEmails() function.
async function getEmails (emailGroup){
const groupResponse = await MailingListGroup.findAll({ where: { mailingListGroup: emailGroup }})
let gropudId = JSON.stringify(groupResponse[0].id);
const emailsResponse = await MailingListEmails.findAll({ where: { mailingListGroup: gropudId }})
const emails = [];
for(let i=0; i<emailsResponse.length; i++){
emails.push(emailsResponse[i].email);
}
return emails;
}

How to define Quaggajs in Asp.Net MVC

I am new using the library quaggajs and it is difficult to find information. I am implementing this library in my project and I am not sure if I am performing the steps correctly. I have added the quagga.js file in the Scripts folder and I have added this to my view and I am having this error:
Uncaught ReferenceError: Quagga is not defined
at Object.init (114:13)
at 224:15
View
#{
ViewBag.Title = "Barcode";
}
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-6">
<div id="interactive" class="viewport"></div>
</div>
<div class="col-xs-12 col-sm-12 col-md-6">
<div id="result_strip">
</div>
</div>
</div>
</div>
</div>
<script>
var AppQuagga = {
init: function () {
var self = this;
Quagga.init(this.state, function (err) {
if (err) {
return self.handleError(err);
}
//Quagga.registerResultCollector(resultCollector);
Quagga.start();
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
setTimeout(function () {
var track = Quagga.CameraAccess.getActiveTrack();
var capabilities = {};
if (typeof track.getCapabilities === 'function') {
try {
capabilities = track.getCapabilities();
track.applyConstraints({ advanced: [{ zoom: 2.5 }] });
} catch (e) { }
}
}, 500);
});
},
handleError: function (err) {
console.log(err);
},
state: {
inputStream: {
type: "LiveStream",
constraints: {
facingMode: "user"
}
},
locator: {
patchSize: "medium",
halfSample: true
},
numOfWorkers: (navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4),
frequency: 20,
decoder: {
readers: [{
format: "code_128_reader",
config: {}
}, {
format: "ean_reader",
config: {
}
}, {
format: "code_39_reader",
config: {}
},
{
format: "codabar_reader",
config: {}
},
//{
// format: "code_39_vin_reader",
// config: {}
//},
//{
// format: "ean_8_reader",
// config: {}
//},{
// format: "upc_reader",
// config: {}
//}, {
// format: "upc_e_reader",
// config: {}
//}, {
// format: "i2of5_reader",
// config: {}
//}, {
// format: "2of5_reader",
// config: {}
//},
{
format: "code_93_reader",
config: {}
}]
},
locate: true
},
lastResult: null
};
AppQuagga.init();
Quagga.onDetected(function (result) {
var code = result.codeResult.code;
if (code != null) {
if (AppQuagga.lastResult !== code) {
AppQuagga.lastResult = code;
var $node = null;
$node = $('<p>Read: ' + code + '</p>');
$("#result_strip").prepend($node);
// window.location.href = '#Url.Action("SerialNumber", "Equipment")' + 'CVHFPD2';
}
}
});
setTimeout(function () {
var track = Quagga.CameraAccess.getActiveTrack();
var capabilities = {};
if (typeof track.getCapabilities === 'function') {
try {
capabilities = track.getCapabilities();
track.applyConstraints({ advanced: [{ zoom: 2.5 }] });
} catch (e) { }
}
}, 500);
</script>
<style>
#interactive.viewport {
position: relative;
}
#interactive.viewport > canvas, #interactive.viewport > video {
max-width: 100%;
width: 100%;
}
canvas.drawing, canvas.drawingBuffer {
position: absolute;
left: 0;
top: 0;
}
.reader-config-group label > span {
width: 50%;
}
.reader-config-group label > select, .reader-config-group label > input {
max-width: calc(50% - 2px);
}
#interactive.viewport {
width: 100%;
height: auto;
overflow: hidden;
}
</style>

Vue-slider has correct data but places both slider-tooltips at the end of the slider

I am using the "vue-slider" component to sort products based on their price. The problem I am facing is that, eventhough the data is correctly loaded and send to the "vue-slider" implementation. The tooltips (the dragable dots) on the slider appear both at the end of the slider.
I would like to have the first tooltip at the beginning of the slider and the second one at the end. The getMin and getMax are read via string interpolation {{getMin}} and {{getMax}} both of these show the right values, 1 and 800 (dollars). This makes me wonder why both tooltips are still at the end of the slider.
I display the slider data in the front-end using the following code:
<price-slider
code="price"
id="reloadDiv"
:priceRange="[
{ from: minPrice },
{ to: maxPrice },
]"
#change="$emitPriceSlider($event)"
/>
</div>
The logic behind this slider is based of the component. The code I use for this is as follows:
<template>
<div class="price-slider-container">
{{ getMin }} {{ getMax }}
<no-ssr placeholder="loading..." placeholader-tag="span">
<vue-slider
ref="priceSlider"
v-model="value"
v-bind="priceSliderOptions"
:clickable="false"
:min="getMin"
:max="getMax"
:tooltip-formatter="tooltipContent"
#drag-end="setPrice"
/>
</no-ssr>
</div>
</template>
<script>
import NoSSR from "vue-no-ssr";
import isEqual from "lodash-es/isEqual";
import { products } from "config";
const PriceSliderComponents = {};
if (process.browser) {
let VueSlider = require("vue-slider-component");
PriceSliderComponents["vue-slider"] = VueSlider;
}
PriceSliderComponents["no-ssr"] = NoSSR;
export default {
name: "PriceSlider",
props: {
content: {
type: null,
default: "",
},
id: {
type: null,
required: true,
},
code: {
type: null,
required: true,
},
priceRange: {
type: Array,
required: true,
},
context: {
type: null,
default: "",
},
},
beforeMount() {
this.$bus.$on("reset-filters", this.resetPriceSlider);
this.$bus.$on("reset-price-slider", this.resetPriceSlider);
},
beforeDestroy() {
this.$bus.$off("reset-filters", this.resetPriceSlider);
this.$bus.$off("reset-price-slider", this.resetPriceSlider);
},
mounted() {
const routeQueryData =
this.$store.state.route[products.routerFiltersSource];
if (routeQueryData.hasOwnProperty("price")) {
const routePriceRange = routeQueryData["price"].split("-");
if (!isEqual(this.value, routePriceRange)) {
this.value = routePriceRange;
}
}
},
data() {
return {
active: false,
remove: false,
value: this.priceRange,
currencySign: this.$store.state.config.i18n.currencySign,
priceSliderOptions: {
clickable: false,
height: 2,
"bg-style": {
backgroundColor: "#f2f2f2",
},
"tooltip-dir": ["bottom", "bottom"],
formatter: "€ {value}",
"process-style": {
backgroundColor: "#4dba87",
fontWeight: 700,
},
"tooltip-style": {
backgroundColor: "#4dba87",
color: "#ffffff",
"border-color": "#4dba87",
padding: "7px 10px",
},
},
};
},
computed: {
// priceSliderOptions() {
// return {
// ...this.priceSliderConfig,
// ...this.tooltipContent,
// silent: true,
// };
// },
tooltipContent() {
return { formatter: this.currencySign + " {value}" };
},
getMin() {
return String(this.priceRange[0].from);
},
getMax() {
return String(this.priceRange[1].to);
},
},
watch: {
$route: "validateRoute",
},
methods: {
setPrice: function (e) {
let val = e.val;
let from = parseInt(val[0]);
let to = parseInt(val[1]);
let id = from.toFixed(1) + "-" + to.toFixed(1);
this.remove = isEqual([from, to], this.priceRange);
this.switchFilter({
id: id,
type: this.code,
from: from,
to: to,
remove: this.remove,
});
},
switchFilter(variant) {
this.$emit("change", variant);
},
resetPriceSlider() {
if (this.$refs.priceSlider) {
this.$refs.priceSlider.setValue(this.priceRange);
}
},
validateRoute() {
const routeQueryData =
this.$store.state.route[products.routerFiltersSource];
if (this.$refs.priceSlider && !routeQueryData.hasOwnProperty("price")) {
this.$nextTick(() => {
this.$refs.priceSlider.setValue(this.priceRange);
});
}
},
},
components: PriceSliderComponents,
};
</script>
<style lang="scss" scoped>
#import "~src/themes/default/css/variables/colors";
#import "~src/themes/default/css/helpers/functions/color";
$color-event: color(tertiary);
$color-active: color(accent);
.price-slider-container {
padding-bottom: 50px;
position: relative;
z-index: 1;
}
.price-selector {
width: 20px;
height: 20px;
&.active {
.square {
background-color: $color-active;
}
}
}
.square {
width: 80%;
height: 80%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
<style lang="scss">
.vue-slider-component .vue-slider-dot {
box-shadow: none;
}
</style>
I have found the solution to this problem in the following line in:
data() {
return {
active: false,
remove: false,
value: this.priceRange,
Where value is set to an array, this is not supported. I patched this by replacing this.priceRange to:
[this.priceRange[0].from, this.priceRange[1].to],

How to access class variable / methods in callback in Typescript?

I'm using high chart API in my angular project, so what I need is when I drilldown to any map location, I've got the state code which I passed into my class level method to do some service stuff in it.
Here is my current code:
ngOnInit() {
this.chartOptions = {
chart: {
height: (8 / 16) * 100 + '%',
events: {
drilldown(e) {
// ERROR Error: this.getVendorProductStatsByStateCode is not a function
this.getVendorProductStatsByStateCode(e.point.drilldown);
const chart = this as any;
const mapKey = 'countries/ca/' + e.point.drilldown + '-all';
const mapData = require(`#highcharts/map-collection/countries/ca/ca-on-all.geo.json`);
const provinceData = Highcharts.geojson(mapData);
provinceData.forEach((el: any, i) => {
el.value = i;
});
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data: provinceData,
dataLabels: {
enabled: true
}
});
chart.setTitle(null, { text: e.point.name });
},
drillup() {
const chart = this as any;
}
}
},
title: {
text: ''
},
colorAxis: {
min: 0,
minColor: '#E6E7E8',
maxColor: '#417BCC'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
plotOptions: {
map: {
states: {
hover: {
color: '#F8BA03'
}
}
}
},
series: [
{
name: 'Canada',
data: caMap
}
],
drilldown: {}
};
}
getVendorProductStatsByStateCode(mapstateCode) {
console.log(mapstateCode);
}
Here is the stackblitz running example
When calling the drilldown function I want to access this.getVendorProductStatsByStateCode, which is in my class component method. What is the right way to achieve it?
You can define your component in a variable and use this variable instead of (this) because it is instance of method not the component like that:
caMap.forEach((el: any, i) => {
el.value = i;
el.drilldown = el.properties['hc-key'];
});
var myComp = this;
this.chartOptions = {
chart: {
height: (8 / 16) * 100 + '%',
events: {
drilldown(e) {
// ERROR Error: this.getVendorProductStatsByStateCode is not a function
myComp.getVendorProductStatsByStateCode(e.point.drilldown);
const chart = this as any;
const mapKey = 'countries/ca/' + e.point.drilldown + '-all';
//Stackbliz wont load data if you pass mapkey as variable. So I use a hard code one in this example.
// const mapData = require(`#highcharts/map-collection/${mapKey}.geo.json`);
const mapData = require(`#highcharts/map-collection/countries/ca/ca-on-all.geo.json`);
const provinceData = Highcharts.geojson(mapData);
// Set a random value on map
provinceData.forEach((el: any, i) => {
el.value = i;
});

Categories