417 lines
15 KiB
JavaScript
417 lines
15 KiB
JavaScript
import dti from 'dom-to-image';
|
|
import './Label.html';
|
|
import PDF from 'jspdf';
|
|
import { saveAs } from 'file-saver';
|
|
import swal from 'sweetalert2';
|
|
import dragula from 'dragula';
|
|
//import JsBarcode from 'JsBarcode';
|
|
import QRCode from '/imports/util/qrcode/qrcode';
|
|
//let QRCode = require('/imports/util/qrcode/qrcode.js');
|
|
|
|
console.log(QRCode);
|
|
|
|
//let {qrcode, svg2url} = require('pure-svg-code');
|
|
//let QRCode = require('qrcode-svg');
|
|
|
|
//******************************************************************
|
|
//** Creates printable labels for a roll style printer.
|
|
//******************************************************************
|
|
|
|
let PREFIX = "LabelMaker_";
|
|
let PX_PER_MM = 300 / 25.4;
|
|
let SCREEN_PX_PER_MM = 96 / 25.4;
|
|
let imagePath = "/images/3x2 Label Logo BW.svg";//"/images/Logo_0.8x0.73_300ppi.png";
|
|
|
|
function generateLabels(title1, title2, ingredients, date, count, topSpacing, bottomSpacing) {
|
|
//TODO: Allow logo to be removed or altered with an alternative logo for sizing fixes
|
|
let label = "<div class='label'>" +
|
|
"<div class='barcodeContainer'><svg class='barcode' jsbarcode-format='UPC' jsbarcode-value='123456789012' jsbarcode-textmargin='0' jsbarcode-fontoptions='bold' jsbarcode-margin='0' jsbarcode-width='2in' jsbarcode-height='10em'></svg></div>" +
|
|
//"<div style='height: " + (topSpacing) + "in'></div>" +
|
|
//"<img class='labelLogo' alt='logo' src='/images/PetitTetonLabelLogo_2in Width_v1.png'/>" +
|
|
"<img class='labelLogo' alt='logo' src='" + imagePath + "'/>" +
|
|
//"<div class='labelTagline'>We grow it. We can it.</div>" +
|
|
"<div class='title1'>" + title1 + "</div>" +
|
|
"<div class='title2'>" + (title2 === undefined ? "" : title2) + "</div>" +
|
|
"<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>:" + ingredients + "</div>" +
|
|
"<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'>8oz</span> FD1951 (" + date + ")</div>" +
|
|
"<div class='instructions'>Refrigerate after opening; return jar when done</div>" +
|
|
"<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>" +
|
|
"<div class='website'>www.PetitTeton.com</div>" +
|
|
//"<div style='height: " + bottomSpacing + "in'></div>" +
|
|
"</div>";
|
|
let labels = "";
|
|
|
|
//TODO: Include bar code and identifying numbers.
|
|
for(let i = 0; i < count; i++) {
|
|
labels += label;
|
|
}
|
|
|
|
return labels;
|
|
}
|
|
|
|
function printImageOld(template, dataUrl) {
|
|
let img = new Image();
|
|
|
|
img.onload = function() {
|
|
let imageCanvas = $('.labelCanvas')[0];
|
|
let ctx = imageCanvas.getContext('2d');
|
|
//let threshold = 255 + 200 + 0;
|
|
let desiredContrast = 100;
|
|
let contrastCorrectionFactor = (259 * (desiredContrast + 255)) / (255 * (259 - desiredContrast));
|
|
|
|
imageCanvas.width = img.width;
|
|
imageCanvas.height = img.height;
|
|
//console.log("Generated image: " + img.width + ", " + img.height);
|
|
//ctx.scale(0.25, 0.25);
|
|
ctx.drawImage(img, 0, 0);
|
|
|
|
let imageData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);
|
|
let data = imageData.data;
|
|
|
|
//Run three times
|
|
for(let c = 0; c < 3; c++) {
|
|
//Set each pixel to either black or white with the given threshold.
|
|
for(let i = 0; i < data.length; i += 4) {
|
|
data[i] = contrastCorrectionFactor * (data[i] - 128) + 128;
|
|
data[i + 1] = contrastCorrectionFactor * (data[i + 1] - 128) + 128;
|
|
data[i + 2] = contrastCorrectionFactor * (data[i + 2] - 128) + 128;
|
|
//if(data[i] + data[i + 1] + data[i + 2] < threshold) {
|
|
// data[i] = 0;
|
|
// data[i + 1] = 0;
|
|
// data[i + 2] = 0;
|
|
//}
|
|
//else {
|
|
// data[i] = 255;
|
|
// data[i + 1] = 255;
|
|
// data[i + 2] = 255;
|
|
//}
|
|
data[i + 3] = 255;
|
|
}
|
|
}
|
|
|
|
ctx.putImageData(imageData, 0, 0);
|
|
|
|
//Convert the canvas content to an image for printing. (cannot print a canvas?)
|
|
//sendToPrinter(template, imageCanvas.toDataURL("image/png"));
|
|
|
|
//Save to disk.
|
|
//imageCanvas.toBlob(function(blob) {
|
|
// saveAs(blob, "label.png");
|
|
//}, "image/png", 1);
|
|
|
|
//imageCanvas.toBlob(function(blob) {
|
|
// let url = URL.createObjectURL(blob);
|
|
// window.open(url, "_blank");
|
|
//}, "image/png", 1);
|
|
|
|
//let imgData = imageCanvas.toDataURL('image/jpeg', 1.0);
|
|
imageCanvas.toBlob(function(blob) {
|
|
let pdf = new PDF();
|
|
let url = URL.createObjectURL(blob);
|
|
pdf.addImage(url, "image/png", 0, 0);
|
|
pdf.save("label.pdf");
|
|
}, "image/png", 1);
|
|
};
|
|
img.src = dataUrl;
|
|
}
|
|
|
|
function printImage(template, raw, width, height) {
|
|
let data = raw;
|
|
//Run three times
|
|
for(let c = 0; c < 3; c++) {
|
|
//Set each pixel to either black or white with the given threshold.
|
|
for(let i = 0; i < data.length; i += 4) {
|
|
data[i] = contrastCorrectionFactor * (data[i] - 128) + 128;
|
|
data[i + 1] = contrastCorrectionFactor * (data[i + 1] - 128) + 128;
|
|
data[i + 2] = contrastCorrectionFactor * (data[i + 2] - 128) + 128;
|
|
//if(data[i] + data[i + 1] + data[i + 2] < threshold) {
|
|
// data[i] = 0;
|
|
// data[i + 1] = 0;
|
|
// data[i + 2] = 0;
|
|
//}
|
|
//else {
|
|
// data[i] = 255;
|
|
// data[i + 1] = 255;
|
|
// data[i + 2] = 255;
|
|
//}
|
|
data[i + 3] = 255;
|
|
}
|
|
}
|
|
|
|
let url = URL.createObjectURL(new Blob(raw, {type: "image/png"}));
|
|
let test = new Image();
|
|
test.src = url;
|
|
$('.testImage').html(test);
|
|
}
|
|
// Note: Not working correctly. Output seems to be at 96dpi instead of 300+dpi. Using a large image scaled down in in an Image tag seems to not print well.
|
|
function sendToPrinter(template, dataUrl) {
|
|
let canvasImg = new Image();
|
|
canvasImg.onload = function() {
|
|
//window.print();
|
|
};
|
|
canvasImg.src = dataUrl;
|
|
canvasImg.style.height = template.labelHeight.get() + "mm";
|
|
canvasImg.style.width = template.labelWidth.get() + "mm";
|
|
$(".printableLabel").html(canvasImg);
|
|
|
|
//$('.printableLabel').html(img);
|
|
window.print();
|
|
}
|
|
|
|
function loadImage(url) {
|
|
return new Promise(r => { let i = new Image(); i.onload = (() => r(i)); i.src = url; });
|
|
}
|
|
async function refreshLabelCanvas(template) {
|
|
let mmWidth = template.labelWidth.get();
|
|
let mmHeight = template.labelHeight.get();
|
|
let title1 = template.title1.get();
|
|
let title1Font = template.title1Font.get();
|
|
let title1YOffset = template.title1YOffset.get();
|
|
let title2 = template.title2.get();
|
|
let title2Font = template.title2Font.get();
|
|
let title2YOffset = template.title2YOffset.get();
|
|
let ingredients = template.ingredients.get();
|
|
let ingredientsFont = template.ingredientsFont.get();
|
|
let ingredientsYOffset = template.ingredientsYOffset.get();
|
|
let date = template.date.get();
|
|
let $labelCanvas = $('.labelCanvas');
|
|
let ctx = $labelCanvas[0].getContext('2d');
|
|
let width = Math.floor(mmWidth * PX_PER_MM);
|
|
let height = Math.floor(mmHeight * PX_PER_MM);
|
|
let center = width / 2;
|
|
|
|
let img = await loadImage(imagePath);
|
|
let imageWidth = 241;
|
|
let imageHeight = 219;
|
|
|
|
let ingredientsY = 180;
|
|
let ingredientsEndingY = 240;
|
|
let instructionsY = 280;
|
|
let addressY = 320;
|
|
let websiteY = 380;
|
|
|
|
ctx.fillStyle = 'white';
|
|
ctx.fillRect(0,0, width, height);
|
|
ctx.fillStyle = 'black';
|
|
ctx.drawImage(img, center - (imageWidth / 2), 0);
|
|
ctx.font = title1Font;
|
|
ctx.textAlign = 'center';
|
|
ctx.fillText(title1, center, title1YOffset);
|
|
|
|
|
|
|
|
////TODO: Allow logo to be removed or altered with an alternative logo for sizing fixes
|
|
//let label = "<div class='label'>" +
|
|
// "<div style='height: " + topSpacing + "in'></div>" +
|
|
// //"<img class='labelLogo' alt='logo' src='/images/PetitTetonLabelLogo_2in Width_v1.png'/>" +
|
|
// "<img class='labelLogo' alt='logo' src='/images/Logo_0.8x0.73_300ppi.png'/>" +
|
|
// "<div class='labelTagline'>We grow it. We can it.</div>" +
|
|
// "<div class='title1'>" + title1 + "</div>" +
|
|
// "<div class='title2'>" + (title2 === undefined ? "" : title2) + "</div>" +
|
|
// "<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>:" + ingredients + "</div>" +
|
|
// "<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'>8oz</span> FD1951 (" + date + ")</div>" +
|
|
// "<div class='instructions'>Refrigerate after opening; return jar when done</div>" +
|
|
// "<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>" +
|
|
// "<div class='website'>www.PetitTeton.com</div>" +
|
|
// "<div style='height: " + bottomSpacing + "in'></div>" +
|
|
// "</div>";
|
|
//let labels = "";
|
|
//
|
|
////TODO: Include bar code and identifying numbers.
|
|
//for(let i = 0; i < count; i++) {
|
|
// labels += label;
|
|
//}
|
|
//
|
|
//return labels;
|
|
}
|
|
function bufferToBase64(buf) {
|
|
var binstr = Array.prototype.map.call(buf, function (ch) {
|
|
return String.fromCharCode(ch);
|
|
}).join('');
|
|
return btoa(binstr);
|
|
}
|
|
|
|
Template.LabelMaker.onCreated(function() {
|
|
this.labelWidth = new ReactiveVar(76);
|
|
this.labelHeight = new ReactiveVar(50);
|
|
|
|
this.title1 = new ReactiveVar("Strawberry");
|
|
this.title2 = new ReactiveVar("w/ Espelette");
|
|
this.ingredients = new ReactiveVar("*strawberry, sugar, *espelette");
|
|
|
|
this.date = new ReactiveVar(19001);
|
|
|
|
//Session.set(PREFIX + "title1", "Strawberry");
|
|
//Session.set(PREFIX + "title1Font", "50px Times New Roman");
|
|
//Session.set(PREFIX + "title1YOffset", 260);
|
|
//Session.set(PREFIX + "title2", "w/ Espelette");
|
|
//Session.set(PREFIX + "title2Font", "40px Times New Roman");
|
|
//Session.set(PREFIX + "title2YOffset", 340);
|
|
//Session.set(PREFIX + "ingredients", "*strawberry, sugar, *espelette");
|
|
//Session.set(PREFIX + "date", 19001);
|
|
//Session.set(PREFIX + "count", 3);
|
|
});
|
|
Template.LabelMaker.onRendered(function() {
|
|
let template = this;
|
|
|
|
//Re-run this routine when ever the session variables change.
|
|
//Tracker.autorun(function() {
|
|
// //refreshLabelCanvas(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), 1, Session.get(PREFIX + "labelSpacing"), 0);
|
|
// refreshLabelCanvas(template);
|
|
//});
|
|
//
|
|
//template.$('.labelContainer').on('DOMSubtreeModified', function() {
|
|
// console.log("Initialized barcode");
|
|
// //
|
|
//});
|
|
//JsBarcode(".barcode").init();
|
|
|
|
|
|
//const svgString = qrcode({content: "1234567890", padding: 0, width: 60, height: 60, color: "#000000", background: "#FFFFFF", ecl: "L"});
|
|
//this.$('.qrcode').attr('src', svg2url(svgString));
|
|
|
|
//this.$('.qrcode').attr('src', svg2url(new QRCode({content: '1234567890', width: 80, height: 80, color: "#000000", background: "#FFFFFF"}).svg()));
|
|
|
|
new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
|
|
});
|
|
Template.LabelMaker.onDestroyed(function() {
|
|
});
|
|
Template.LabelMaker.events({
|
|
'change .labelWidth': function(e, t) {
|
|
let x = $(e.target).val();
|
|
|
|
t.labelWidth.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 76);
|
|
},
|
|
'change .labelHeight': function(event, template) {
|
|
let x = $(event.target).val();
|
|
|
|
t.labelHeight.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 50);
|
|
},
|
|
|
|
'change .title1': function(e, t) {t.title1.set($(e.target).val());},
|
|
'change .title1Font': function(e, t) {t.title1Font.set($(e.target).val());},
|
|
'change .title1YOffset': function(e, t) {t.title1YOffset.set(parseInt($(e.target).val()));},
|
|
|
|
'change .title2': function(e, t) {t.title2.set($(e.target).val());},
|
|
'change .title2Font': function(e, t) {t.title2Font.set($(e.target).val());},
|
|
'change .title2YOffset': function(e, t) {t.title2YOffset.set(parseInt($(e.target).val()));},
|
|
|
|
'change .ingredients': function(e, t) {t.ingredients.set($(e.target).val());},
|
|
'change .ingredientsFont': function(e, t) {t.ingredientsFont.set($(e.target).val());},
|
|
'change .ingredientsYOffset': function(e, t) {t.ingredientsYOffset.set(parseInt($(e.target).val()));},
|
|
|
|
'change .date': function(e, t) {t.date.set(parseInt($(e.target).val()));},
|
|
'click .preview': function(event, template) {
|
|
let params = {};
|
|
|
|
params['title1'] = "Strawberry";
|
|
params['title2'] = "";
|
|
params['ingredients'] = "Fairies";
|
|
params['date'] = "1234";
|
|
window.open('/PrintLabel?' + $.param(params));
|
|
},
|
|
'click .print': function(event, template) {
|
|
let _this = template;
|
|
let node = $('.label')[0];
|
|
let width = _this.labelWidth.get();
|
|
let height =_this.labelHeight.get();
|
|
let title1 =_this.title1.get();
|
|
let title2 =_this.title2.get();
|
|
let ingredients =_this.ingredients.get();
|
|
let date =_this.date.get();
|
|
|
|
Meteor.call('printLabels', width, height, "3x2Standard", title1, title2, ingredients, date, (error, result) => {
|
|
if(error) {
|
|
console.log(error);
|
|
}
|
|
else {
|
|
const blob = new Blob([result], {type: 'application/pdf'});
|
|
const link = document.createElement('a');
|
|
link.href = window.URL.createObjectURL(blob);
|
|
link.download = "labels.pdf";
|
|
link.click();
|
|
}
|
|
});
|
|
|
|
//dti.toBlob(node, {bgcolor: 'white'}).then(function(blob) {
|
|
// printImage(template, blob);
|
|
//}).catch(function(err) {
|
|
// console.log(err);
|
|
//});
|
|
|
|
//dti.toPng(node, {bgcolor: 'white'}).then(function(dataUrl) {
|
|
// printImageOld(template, dataUrl);
|
|
//}).catch(function(err) {
|
|
// console.log(err);
|
|
//});
|
|
|
|
|
|
//let count = template.$('input[name="count"]').val();
|
|
//let spacing = Session.get(PREFIX + "labelSpacing");
|
|
//
|
|
////count = (count === undefined || Number.isNaN(count)) ? 1 : parseInt(count);
|
|
////
|
|
////if(count < 1) {
|
|
//// count = 1;
|
|
////}
|
|
////
|
|
////Session.set(PREFIX + "generatedLabels", generateLabels(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), count, 0, spacing));
|
|
//
|
|
//let $label = $('.printableLabel');
|
|
//
|
|
//console.log($label);
|
|
//console.log($label.length);
|
|
//domtoimage.toPng($label).then(function(dataUrl) {
|
|
// console.log("A");
|
|
// let img = new Image();
|
|
// img.src = dataUrl;
|
|
// $('.printableLabel').html(img);
|
|
// //caman('.printableLabel img', function() {
|
|
// // this.contrast(100);
|
|
// // this.render();
|
|
// // window.print();
|
|
// //});
|
|
//}).catch(function(error) {
|
|
// console.error("failed to convert dom to image");
|
|
// console.error(error);
|
|
//});
|
|
}
|
|
});
|
|
Template.LabelMaker.helpers({
|
|
title1: function() {return Template.instance().title1.get();},
|
|
title2: function() {return Template.instance().title2.get();},
|
|
ingredients: function() {return Template.instance().ingredients.get();},
|
|
date: function() {return Template.instance().date.get();},
|
|
labelWidth: function() {return Template.instance().labelWidth.get();},
|
|
labelHeight: function() {return Template.instance().labelHeight.get();},
|
|
sampleLabel: function() {
|
|
let t = Template.instance();
|
|
setTimeout(function() {JsBarcode(".barcode").init();}, 500);
|
|
return generateLabels(t.title1.get(), t.title2.get(), t.ingredients.get(), t.date.get(), 1, 0);
|
|
},
|
|
//canvasLabel: function() {
|
|
// return generateLabelCanvas(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), 1, Session.get(PREFIX + "labelSpacing"), 0);
|
|
//},
|
|
labels: function() {
|
|
return Session.get(PREFIX + "generatedLabels");
|
|
},
|
|
labelPxWidth: function() {
|
|
//console.log("label width: " + Template.instance().labelWidth.get());
|
|
//console.log("px_per_mm: " + PX_PER_MM);
|
|
//console.log("labelPxWidth: " + (Template.instance().labelWidth.get() * PX_PER_MM));
|
|
return Math.floor(Template.instance().labelWidth.get() * PX_PER_MM);
|
|
},
|
|
labelPxHeight: function() {
|
|
return Math.floor(Template.instance().labelHeight.get() * PX_PER_MM);
|
|
},
|
|
labelPxWidthActual: function() {
|
|
//console.log("label width: " + Template.instance().labelWidth.get());
|
|
//console.log("px_per_mm: " + PX_PER_MM);
|
|
//console.log("labelPxWidth: " + (Template.instance().labelWidth.get() * PX_PER_MM));
|
|
return Math.floor(Template.instance().labelWidth.get() * SCREEN_PX_PER_MM);
|
|
},
|
|
labelPxHeightActual: function() {
|
|
return Math.floor(Template.instance().labelHeight.get() * SCREEN_PX_PER_MM);
|
|
}
|
|
});
|