How to define Quaggajs in Asp.Net MVC - javascript

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>

Related

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;
}

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],

Hierarchical Chart in Kendo

I am creating a project using javascript with kendo. In my project there is a requirement to implement hierarchical chart. I research this type of chart in kendo and could not get the exact result. Here is the demo code:
function localDataSource(options) {
var id = options.schema.model.id;
var data = options.data;
var newId = -1;
var created, updated, deleted;
var dataSource = new kendo.data.DataSource($.extend(true, {
transport: {
read: function(e) {
created = {};
updated = {};
deleted = {};
e.success(data || []);
},
update: function(e) {
var item = e.data;
if (!created[item[id]]) {
updated[item[id]] = item;
}
e.success();
},
destroy: function(e) {
var idValue = e.data[id];
if (!created[idValue]) {
deleted[idValue] = e.data;
} else {
delete created[idValue];
}
e.success();
},
create: function(e) {
var item = e.data;
item[id] = newId--;
created[item[id]] = $.extend(true, {}, item);
e.success(item);
}
},
}, options));
dataSource.getChanges = function() {
return {
deleted: toArray(deleted),
created: toArray(created),
updated: toArray(updated)
}
};
return dataSource;
}
function toArray(changes) {
var result = [];
for (var id in changes) {
result.push(changes[id]);
}
return result;
}
function createDiagram() {
var shapesDataSource = localDataSource({
data: [{
"Id": 1,
"JobTitle": "President"
}, {
"Id": 2,
"JobTitle": "VP Finance",
"Color": "#3399cc"
}, {
"Id": 3,
"JobTitle": "VP Customer Relations",
"Color": "#3399cc"
}, {
"Id": 4,
"JobTitle": "VP Human Resources",
"Color": "#3399cc"
}],
schema: {
model: {
id: "Id",
fields: {
Id: {
type: "number",
editable: false
},
JobTitle: {
type: "string"
},
Color: {
type: "string"
}
}
}
}
});
var connectionsDataSource = localDataSource({
data: [{
"Id": 1,
"FromShapeId": 1,
"ToShapeId": 2
}, {
"Id": 2,
"FromShapeId": 1,
"ToShapeId": 3
}, {
"Id": 3,
"FromShapeId": 1,
"ToShapeId": 4
}],
schema: {
model: {
id: "Id",
fields: {
Id: {
type: "number",
editable: false
},
from: {
from: "FromShapeId",
type: "number"
},
to: {
from: "ToShapeId",
type: "number"
}
}
}
}
});
var changesViewModel = kendo.observable({
showChanges: function() {
var diagram = $("#diagram").data("kendoDiagram");
this.set("shapes", diagram.dataSource.getChanges());
this.set("connections", diagram.connectionsDataSource.getChanges());
this.set("visible", true);
},
shapes: {
deleted: [],
created: [],
updated: []
},
connections: {
deleted: [],
created: [],
updated: []
}
});
kendo.bind($("#changes"), changesViewModel);
$("#diagram").kendoDiagram({
dataSource: shapesDataSource,
connectionsDataSource: connectionsDataSource,
layout: {
type: "tree",
subtype: "tipover",
underneathHorizontalOffset: 140
},
shapeDefaults: {
visual: visualTemplate,
content: {
template: "#= dataItem.JobTitle #",
fontSize: 17
}
},
connectionDefaults: {
stroke: {
color: "#586477",
width: 2
}
},
dataBound: onDataBound
});
}
$(document).ready(createDiagram);
function visualTemplate(options) {
var dataviz = kendo.dataviz;
var g = new dataviz.diagram.Group();
var dataItem = options.dataItem;
if (dataItem.JobTitle === "President") {
g.append(new dataviz.diagram.Circle({
radius: 60,
stroke: {
width: 2,
color: dataItem.Color || "#586477"
},
fill: "#e8eff7"
}));
} else {
g.append(new dataviz.diagram.Rectangle({
width: 240,
height: 67,
stroke: {
width: 0
},
fill: "#e8eff7"
}));
g.append(new dataviz.diagram.Rectangle({
width: 8,
height: 67,
fill: dataItem.Color,
stroke: {
width: 0
}
}));
}
return g;
}
function onDataBound(e) {
this.bringIntoView(this.shapes);
}
<html>
<head>
<meta charset="utf-8" />
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2016.1.412/styles/kendo.common.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2016.1.412/styles/kendo.rtl.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2016.1.412/styles/kendo.silver.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2016.1.412/styles/kendo.mobile.all.min.css" />
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2016.1.412/js/kendo.all.min.js"></script>
</head>
<body>
<div id="diagram"></div>
<div id="changes">
<button type="button" class="k-button" data-bind="click:showChanges">Show changes</button>
<div data-bind="visible:visible">
Deleted Shapes:
<div data-bind="source: shapes.deleted" data-template="shapeItemTemplate">
</div>
<hr /> Created Shapes:
<div data-bind="source: shapes.created" data-template="shapeItemTemplate">
</div>
<hr /> Updated Shapes:
<div data-bind="source: shapes.updated" data-template="shapeItemTemplate">
</div>
<hr /> Deleted Connections:
<div data-bind="source: connections.deleted" data-template="connectionItemTemplate">
</div>
<hr /> Created Connections:
<div data-bind="source: connections.created" data-template="connectionItemTemplate">
</div>
<hr /> Updated Connections:
<div data-bind="source: connections.updated" data-template="connectionItemTemplate">
</div>
</div>
</div>
<script type="text/kendo" id="shapeItemTemplate">
<div>
JodTitle: #:JobTitle#
</div>
</script>
<script type="text/kendo" id="connectionItemTemplate">
<div>
#console.log(data)# #:FromShapeId# - #:ToShapeId#
</div>
</script>
</body>
</html>
But i need below type of graph with clickable circle.
Please help me to fix this problem

Extract Font Name from PDF

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.

sencha navigation view overlapping on home listview

I am using sencha navigation view in my sencha application .
my bug scenario
I have list view with images on home screen first time it's load 20 record then scroll to down record will be increase by 20 on every scroll when i click on any image and redirect to another view like image detail view or profile view and come back to home on pressing back button all the images overlapped.
please help i am trying to solve this bug before 10 day's but not get success :- before overlapping
1) I am using navigation view it's extend with "Ext.dataview.DataView" and there is using
useComponents: true,
defaultType: 'productlistitem'
2) In 'productlistitem' extend with 'Ext.dataview.component.DataItem' In this view I am using update method witch set the image and other component data and also using dynamically method for image width , height .
below you can check my all views code
A) Home.js
Ext.define('demo.view.home.Home', {
extend: 'Ext.dataview.DataView',
requires: [
'demo.view.product.ListItem',
'demo.view.layout.ColumnLayout'
],
xtype: 'home',
config: {
scrollable: true,
plugins: {
xclass: 'demo.plugin.DataViewPaging', // Reference plugin by class
autoPaging: true
},
autoDestroy: true,
store: 'LookStore',
margin:'2 0',
useComponents: true,
defaultType: 'productlistitem',
cls: 'wow-home',
layout: {
type: 'column',
columnCount: 2,
columnWidth: 160
}
}
});
B) ListItem.js
var listItemData=[];
Ext.define('demo.view.product.ListItem', {
extend: 'Ext.dataview.component.DataItem',
requires: ['demo.view.product.Item'],
xtype: 'productlistitem',
config: {
padding: 2,
zIndex:999,
items: [{
xtype: 'item'
}]
},
initialize: function() {
console.log('initing the list item ');
var me = this;
me.callParent(arguments);
this.on('heightchange', 'recalculateHeight', me, {
delegate: '> item'
});
},
recalculateHeight: function() {
var me = this;
me.setHeight(me.innerElement.getHeight());
},
updateRecord: function(record) {
if (!record) {
return;
}
var me = this,
item = me.down('item');
me.callParent(arguments);
if (item) {
item.updateRecord(record, me.getDataview());
}
listItemData.push(item.id);
}
});
c) Item.js
Ext.define('demo.view.product.Item', {
extend: 'Ext.Container',
xtype: 'item',
requires: [
'Ext.Carousel',
'demo.view.product.ItemImage',
'demo.view.product.UserInfo',
'demo.view.product.InfoLabel'
],
config: {
record: null,
baseCls: 'wow-item',
showDescription: false,
items: [{
xtype: 'itemimage',
width: '100%'
}, {
xtype: 'userinfo',
height: 40,
listeners: {
painted: function() {
if (!this.element.hasListener('tap')) {
this.element.on('tap', function(e) {
e.stopPropagation();
var record = this.scope.up('item').getRecord();
if (!this.scope.getHandleListeners()) {
if(Ext.ComponentQuery.query('main')[0].getActiveItem().xtype === "wardrobedrawer")
demo.app.getController('ProductController').openProductDetail('', '', '', record);
return;
}
if (record && !Ext.isEmpty(record.raw.product_id) && !Ext.isEmpty(record.raw.importer)) {
var brandMerchantProducts = this.scope.up('brandmerchantproducts');
if (brandMerchantProducts) {
var currentTitle = demo.app.getController('HomeController').getMain().getActiveItem().config.title;
var currentItem = this.scope.element.dom.textContent;
if (currentTitle.toUpperCase() !== currentItem.toUpperCase()) {
demo.app.getController('ProductController').showMerchantProducts(record);
}
return;
}
demo.app.getController('ProductController').showMerchantProducts(record);
} else {
var list = this.scope.up('list');
demo.app.getController('ProfileController').goToOtherUserProfile(list, null, null, record.get('merchantId'), e);
}
}, {
scope: this
});
}
}
}
},
{
xtype: 'container',
height: 40,
margin:'1 0 0 0',
name: 'infoContainer',
layout:'hbox',
defaults: {
xtype: 'infolabel',
flex: 1
},
items: [{
iconCls: 'icon-diamond',
text: '09',
itemId: 'wows',
listeners: {
painted: function() {
if (!this.element.hasListener('tap')) {
this.element.on('tap', function(e) {
e.stopPropagation();
var record = this.scope.up('item').getRecord();
if (record.get('type') == 'product') {
demo.app.getController('ProductController').wowOrUnwowHomeProduct(record, this.scope.up('item'));
}
if (record.get('type') === 'look') {
demo.app.getController('ProductController').wowOrUnwowHomeLook(record, this.scope.up('item'));
}
}, {
scope: this
});
}
}
}
}, {
iconCls: 'icon-drawer',
text: '11',
itemId: 'lookOrAdd',
listeners: {
painted: function() {
if (!this.element.hasListener('tap')) {
this.element.on('tap', function(e) {
e.stopPropagation();
var record = this.scope.up('item').getRecord();
if (record.get('type') == 'product') {
demo.addedProductItem = this.scope.up('item');
demo.app.getController('ProductController').addProduct(record);
}
if (record.get('type') === 'look') {
demo.app.getController('ProductController').addHomeLook(record, this.scope.up('item'));
}
}, {
scope: this
});
}
}
}
}]
}
]
},
initialize: function() {
var me = this;
me.callParent(arguments);
me.on('load', 'imageLoaded', me, {
delegate: 'itemimage'
});
},
imageLoaded: function() {
var me = this;
me.setHeight(me.element.getHeight());
},
updateRecord: function(item, dataview) {
if (!item) {
return;
}
if (dataview && dataview.config.showDescription) {
this.setShowDescription(true);
}
var me = this;
me.setRecord(item);
if (item) {
var itemImage = this.down('itemimage'),
images = item.get('images'),
wows = item.get('wows') + '',
adds = item.get('adds') + '',
userInfo = this.down('userinfo');
if (images && images.length) {
itemImage.setSrc(images[0].original);
}
var type = item.get('type');
var lookOrProduct = me.down('#lookOrAdd');
var added = item.get('added');
var icon;
if (type === 'product') {
icon = 'icon-add-drawer';
lookOrProduct.setIconCls(icon);
} else {
icon = added ? 'icon-counterlook' : 'icon-addlookbook';
lookOrProduct.setIconCls(icon);
}
if (!Ext.isEmpty(item.raw.product_id)) {
userInfo.setAvatar('');
} else { // USER
var importer = item.get('importer');
if (importer) {
var avatar = importer.avatar;
if (avatar) {
userInfo.setAvatar(avatar);
} else {
userInfo.setAvatar('resources/images/default/default_avatar.jpg');
}
}
}
me.down('#wows').setText(wows);
if (!item.get('wowed')) {
me.down('#wows').addCls('grayedout-cls');
} else {
me.down('#wows').removeCls('grayedout-cls');
}
lookOrProduct.setText(adds);
if (!item.get('added')) {
lookOrProduct.addCls('grayedout-cls');
} else {
lookOrProduct.removeCls('grayedout-cls');
}
var infoContainer = this.down('container[name=infoContainer]');
if (infoContainer && infoContainer.isHidden()) {
infoContainer.show();
}
var title = Ext.ComponentQuery.query('main')[0].getActiveItem().title;
var storeId = this._record.stores[0].getStoreId();
if (type === 'product' && !Ext.isDefined(title) && storeId !== 'WowedStore' && storeId !== 'SearchStore' && storeId !== 'BrandMerchatProducts') {
var homeUrl = this._record.stores[0].getProxy().getUrl();
if ((homeUrl === demo.model.Config.apiServerPath('home')) || (homeUrl === demo.model.Config.apiServerPath('home'))) {
var noOfProducts = Ext.ComponentQuery.query('#productsInTheListId').length;
if (noOfProducts === 1) {
userInfo.setUsername(item);
if (me.getShowDescription()) {
infoContainer.hide();
userInfo.setAvatar('');
userInfo.setUsername(item);
userInfo.setHandleListeners(false);
}
} else {
userInfo.setUsername(item.get('author'));
if (me.getShowDescription()) {
infoContainer.hide();
userInfo.setAvatar('');
userInfo.setUsername(item.get('description'));
userInfo.setHandleListeners(false);
}
}
} else {
userInfo.setUsername(item);
if (me.getShowDescription()) {
infoContainer.hide();
userInfo.setAvatar('');
userInfo.setUsername(item);
userInfo.setHandleListeners(false);
}
}
} else {
userInfo.setUsername(item.get('author'));
if (me.getShowDescription()) {
infoContainer.hide();
userInfo.setAvatar('');
userInfo.setUsername(item.get('description'));
userInfo.setHandleListeners(false);
}
}
}
},
updateColorOfItem: function(item) {
var me = this,
lookOrProduct = me.down('#lookOrAdd');
if (!item.get('wowed')) {
me.down('#wows').addCls('grayedout-cls');
} else {
me.down('#wows').removeCls('grayedout-cls');
}
if (!item.get('added')) {
lookOrProduct.addCls('grayedout-cls');
} else {
lookOrProduct.removeCls('grayedout-cls');
}
}
});
D) ItemImage.js
Ext.define('demo.view.product.ItemImage', {
extend: 'Ext.Img',
xtype: 'itemimage',
config: {
},
onLoad: function(event) {
var me = this,
width = me.getParent().element.getWidth(), // me.element.getWidth() should work but I have found that sometimes it gives a width of 0. Now I go with a width of the parent.
imageObject = me.imageObject,
naturalWidth = imageObject.width,
naturalHeight = imageObject.height,
naturalRatio = naturalHeight / naturalWidth,
newHeight = naturalRatio * width;
me.setHeight(newHeight);
//Ext.ComponentQuery.query('productlistitem')[0].setHeight(newHeight+84);
me.callParent(event);
}
});
E) UserInfo.js
Ext.define('demo.view.product.UserInfo', {
extend: 'Ext.Container',
requires: ['Ext.Img'],
xtype: 'userinfo',
config: {
avatar: null,
username: null,
baseCls: 'wow-user-info',
handleListeners: true
},
applyAvatar: function(avatar) {
if (Ext.isEmpty(avatar)) {
return null;
}
return Ext.factory({
src: avatar,
cls: 'wow-avatar',
docked: 'left'
}, 'Ext.Img');
},
updateAvatar: function(newAvatar, oldAvatar) {
if (newAvatar) {
this.add(newAvatar);
}
if (oldAvatar) {
oldAvatar.destroy();
}
},
applyUsername: function(item) {
if (Ext.isObject(item)) {
var price_value = "",
price_currency = "",
itemName = "";
if (Ext.isDefined(item.raw.price)) {
if (Ext.isDefined(item.raw.price.value)) {
price_value = item.raw.price.value.toString();
}
}
if (Ext.isDefined(item.raw.price)) {
if (Ext.isDefined(item.raw.price.currency)) {
price_currency = item.raw.price.symbol;
}
}
if (item.raw.description === null) {
var item = item.data.author;
} else {
var item = item.raw.description;
}
item = item.toLowerCase();
itemName = item.charAt(0).toUpperCase() + item.slice(1);
if (Ext.isDefined(price_currency) && Ext.isDefined(price_value) && (price_currency !== "") && (price_value !== "")) {
itemName = '<div class="itemNames"><span style="font-size:0.9em" >' + price_currency.bold() + ' ' + price_value.bold() + '</span>' + " " + '<span style=" font-size:0.8em" class="itemName">' + itemName + '</span>' + '</div>';
} else {
itemName = '<div class="itemNames"><span style=" font-size:0.8em" class="itemName">' + itemName + '</span></div>';
}
return Ext.factory({
html: itemName,
xtype: 'component',
cls: 'wow-username-product'
});
} else {
return Ext.factory({
html: item,
xtype: 'component',
cls: 'wow-username'
});
}
},
updateUsername: function(newUsername, oldUsername) {
if (newUsername) {
this.add(newUsername);
}
if (oldUsername) {
oldUsername.destroy();
}
}
});
F) InfoLabel.js
Ext.define('demo.view.product.InfoLabel', {
extend: 'Ext.Button',
xtype: 'infolabel',
config: {
iconAlign: 'left',
cls: 'wow-info-label'
},
initialize: function() {
// Do nothing stopping unnecessary event listeners being added.
}
});

Categories