Files
PetitTetonMeteor/imports/ui/Label.js

417 lines
15 KiB
JavaScript
Raw Normal View History

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