I have been trying to print to multiple printers with QZ tray using the examples provided here https://qz.io/wiki/2.0-Raw-Printing#promise-loop
but I am getting an error saying TypeError: Cannot read property 'sendData' of null
I have rsvp-3.1.0.min.js, sha-256.min.js and qz-tray.js included.
I use the exact same code provided by the example but obviously changed the printers names to the ones I have installed.
Everything works fine if I try to print to each printer separately (the default way of doing it)
Any idea of what could be wrong or if I am missing a library or something?
Thank you
This is the full error message on Safari:
TypeError: Cannot read property 'sendData' of null
at qz-tray.js:323
at lib$rsvp$$internal$$initializePromise (rsvp-3.1.0.min.js:10)
at new lib$rsvp$promise$$Promise (rsvp-3.1.0.min.js:10)
at Object.promise (qz-tray.js:456)
at Object.dataPromise (qz-tray.js:314)
at Object.find (qz-tray.js:788)
at link (test.html:388)
at lib$rsvp$$internal$$tryCatch (rsvp-3.1.0.min.js:10)
at lib$rsvp$$internal$$invokeCallback (rsvp-3.1.0.min.js:10)
at rsvp-3.1.0.min.js:10
So I found the problem and it was my own mistake, I forgot to initiate QZ tray, the script works perfectly, tested sending a Pixel job to a laser printer and a Raw job to a thermal printer.
EDIT: Solution
function promiseLoop() {
var data = [
"^XA\n^FO50,50^ADN,36,20^FDPRINT 1 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 2 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 3 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 4 ^FS\n^XZ\n"
];
var configs = [
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" }
];
var chain = [];
for(var i = 0; i < data.length; i++) {
(function(i_) {
//setup this chain link
var link = function() {
return qz.printers.find(configs[i_].printer).then(function(found) {
return qz.print(qz.configs.create(found), [data[i_]]);
});
};
chain.push(link);
})(i);
//closure ensures this promise's concept of `i` doesn't change
}
//can be .connect or `Promise.resolve()`, etc
var firstLink = new RSVP.Promise(function(r, e) { r(); });
var lastLink = null;
chain.reduce(function(sequence, link) {
lastLink = sequence.then(link);
return lastLink;
}, firstLink);
//this will be the very last link in the chain
lastLink.catch(function(err) {
console.error(err);
});
}
//Always make sure you are establishing a connection before printing
qz.websocket.connect().then(promiseLoop).catch(errorHandler);
Related
I am trying to create a chrome app that displays when a certain Bluetooth device is sending data. specifically, I have 2 bluetooth mice and I want to identify which one is being moved at a specific time.
I followed the Chrome dev doc and was successful until I tried to implement adding a listener on receive to view the data coming from the device. I am getting a "Cannot read property 'addListener' of undefined" error.
This is when I started getting this error:
Error message
Here's the code I'm working with
chrome.bluetooth.getDevices(function(devices) {
for (var i = 0; i < devices.length; i++) {
//Displaying device names
console.log(i+": "+devices[i].name);
}
//uuid for a specific device
var uuid = "00001200-0000-1000-8000-00805f9b34fb";
// var uuid = devices[4].uuid;
var onConnectedCallback = function() {
if (chrome.runtime.lastError) {
console.log("Connection failed: " + chrome.runtime.lastError.message);
} else {
// Profile implementation here.
}
};
chrome.bluetoothSocket.create(function(createInfo) {
chrome.bluetoothSocket.connect(createInfo.socketId,
devices[4].address, uuid, onConnectedCallback);
console.log(createInfo);
chrome.bluetoothSocket.onRecieve.addListener(function(receiveInfo) {
if (receiveInfo.socketId != socketId)
return;
console.log(receiveInfo);
});
});
});
Checked out this docs and managed to see a similar code snippet:
chrome.bluetoothSocket.onRecieve.addListener(function(receiveInfo) {
if (receiveInfo.socketId != socketId)
return;
// receiveInfo.data is an ArrayBuffer.
});
If you look at it carefully, it seems there was a typo in the sample at the onRecieve part. It should be onReceive. You can see a correct sample here.
I before E, except after C.
I have this simple JSON file, containing paths to folders and image files inside of it:
{ "foldery" : [
{
"foName": "website/img/post1",
"files" : [
"website/img/post1/a.jpeg",
"website/img/post1/b.jpg",
"website/img/post1/c.jpeg",
"website/img/post1/d.jpg",
"website/img/post1/e.jpeg",
"website/img/post1/f.jpg",
"website/img/post1/g.jpg",
"website/img/post1/h.jpg"
]
},
{
"foName": "website/img/postdrugi",
"files" : [
"website/img/postdrugi/20150530_111106.jpg",
"website/img/postdrugi/20150530_113842.jpg",
"website/img/postdrugi/20150530_131251.jpg",
"website/img/postdrugi/20151022_165146.jpg"
]
}
]
}
And a small getJSON function fired on a click of an element:
function getImages(dir){
function select(o) {
var length = o.foldery.length;
//getting the length, and firing a for for all of it's elements
for(var i = 0; i < length; i++){
if (o.foldery[i].foName == dir) {
// if the foName is the same as the functions argument, place 'files' of it into array
return o.foldery[i].files;
}
}
}
$.getJSON("nameindex.json", function(o) {
console.log("getJSON success");
var result = select(o);
var $thmb = $(".thmb .sec");
var thumbLength = 0;
$thmb.children().remove();
for(var i = 0; i < result.length; i++){
$thmb.append('<div class="img"><img src="'+result[i]+'" alt=""/></div>');
}
}).fail( function(d, textStatus, error) {
console.error("getJSON failed, status: " + textStatus + ", error: " + error);
});
}
Now, one day ago the function worked fine on my laptop. Today I moved all the files to and identical settings WAMP on a different PC, ran the code on chrome (same as worked before)....and nothing happens. The 'failed' function returns me this:
getJSON failed, status: parsererror, error: SyntaxError: Unexpected
token ]
Which is weird because the JSON file (if my linter isn't lying to me) is written properly.
On the page I've witnessed the error jQuery is placed at the beginning of <body> tags, but I've been getting the same issue everywhere else.
All the other jQuery elements on the webpage work just fine.
Has anyone else witnessed this problem and possibly knows a workaround?
Also it would be nice to provide a small explanation on why is this error happening.
EDIT: Okay so this now works. It started to work by itself
Still not deleting or posting an answer to this question, because I'm truly curious what was wrong with it before.
Small update: The code seems highly unstable even on the same machine. For instance. Sometimes it works for file1.json and doesn't work for file2.json even if file2 is a direct copy of file1.
I have made a following custom logs function to print all console log messages. Using this function I can control with a single flag variable to either print or not logs throughout the app.
var Utilities = {
showLogs: true,
printLog: function (msg) {
if (this.showLogs) {
console.log(msg);
}
}
};
and I call it as:
Utilities.printLog("a message to print on console");
It works fine as expected. But it has one limitation i.e. its not showing the correct line no# and file name where this was called to print the logs.
One solution is to provide extra parameters to print line no# & file name along with the message.
for instance:
Utilities.printLog("a message to print on console", "10","common.js");
Utilities.printLog("a message to print on console", "310","myLib.js");
I dont want these extra parameters and like to know if there is another option available.
Update:
I tried the V8's Stack Trace API http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi but it only helps in cases when an exception is generated inside try catch block.
First override the Error.prepareStackTrace and create a tracing function like this:
Error.prepareStackTrace = function(error, stack) {
return stack;
};
function getTrace(e) {
var stack = e.stack;
var trace = "";
for (var i = 0; i < stack.length; i++) {
trace += "\r" + stack[i];
}
return trace;
}
and created two sample js files.
libObj.js
var libObj = {
getCube: function(x){
return mathLib.cube( x );
}
};
mathLib.js
var mathLib = {
cube: function(x){
return evilObj * x * x; //see the undefined evilObj --- lets catch trace here
}
};
Now from a third js file (or in my case inside the HTML file) I call the function within the try catch block to see the precise trace of the vulnerable code.
<script type="text/javascript">
try {
var results;
results = libObj.getCube(2);
console.log( results );
} catch (e) {
console.log( getTrace(e));
}
</script>
Now I get below trace of the vulnerable code:
Note:- If you do not override the Error.prepareStackTrace then it gives, I think pretty formatted trace...though both have same info.
Without overriding Error.prepareStackTrace:
Now the question remains open, how I can capture similar trace for my custom logs function as defined above.
You could do this:
var Utilities=
{
showLogs:true,
printLog:function(msg){
if(!this.showLogs) return 0;
var k=new Error().stack.split("\n").slice(2);
k.unshift(msg);
console.log(k.join("\n"));
}
}
I'm developing a small Chrome extension that would allow me to save some records to chrome.storage and then display them.
I've managed to make the set and get process work as I wanted (kinda), but now I'd like to add a duplicate check before saving any record, and I'm quite stuck trying to find a nice and clean solution.
That's what I came up for now:
var storage = chrome.storage.sync;
function saveRecord(record) {
var duplicate = false;
var recordName = record.name;
storage.get('records', function(data) {
var records = data.records;
console.log('im here');
for (var i = 0; i < records.length; i++) {
var Record = records[i];
if (Record.name === recordName) {
duplicate = true;
break;
} else {
console.log(record);
}
}
if (duplicate) {
console.log('this record is already there!');
} else {
arrayWithRecords.push(record);
storage.set({ bands: arrayWithRecords }, function() {
console.log('saved ' + record.name);
});
}
});
}
I'm basically iterating on the array containing the records and checking if the name property already exists. The problem is it breaks basic set and get functionality -- in fact, when saving it correctly logs 'im here' and the relative record object, but it doesn't set the value. Plus, after a while (generally after trying to list the bands with a basic storage.get function) it returns this error:
Error in response to storage.get: TypeError: Cannot read property
'name' of null
I'm guessing this is due to the async nature of the set and get and my incompetence working with it, but I can't get my head around it in order to find a better alternative. Ideas?
Thanks in advance.
I grabbed a bit of code to do some paging with jQuery, via Luca Matteis here
Paging Through Records Using jQuery
I've made some edits to the paging script so that I can use the same code to provide paging of different content in different locations on the same site.
For the most part, I think it works, except that I get a jsonObj is undefined error in firebug.
When I use alert(jsonObj.toSource()), I am shown the variables that I am trying to populate, but at the same time, the script dies because of the error.
I can't figure out why I am getting this conflict of 'undefined' and yet I can easily out put the 'undefined' values in an alert. I can even say alert(jsonObj.name), and it will give me that value, but still launch an jsonObj is undefined error.
Here's the code I'm using
var pagedContent = {
data: null
,holder: null
,currentIndex : 0
,init: function(data, holder) {
this.data = data;
this.holder=holder;
this.show(0); // show last
}
,show: function(index) {
var jsonObj = this.data[index];
if(!jsonObj) {
return;
}
var holdSubset='';
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
this.currentIndex = index;
if(this.holder=='div#firstList'){
var returnedId = jsonObj.id;
var returnedName = jsonObj.name;
var calcScore=this.data[index+i].score/this.data[0].score*100;
var resultInput="<div ' id='"+returnedId+"'><div class='name'>"+returnedName+"</div><div class='score'><div style='width:"+calcScore+"%;'></div></div>";
}
if(this.holder=='div#secondList'){
var name=jsonObj.name;
var city=jsonObj.city;
var region=jsonObj.state;
var resultInput='<li><div>'+name+'</div<div>'+city+'</div><div>'+region+'</div></li>';
}
holdSubset= holdSubset+resultInput;
}
jQuery(this.holder).html('<br/>'+holdSubset);
if(index!=0){
var previous = jQuery("<a>").attr("href","#").click(this.previousHandler).text("< previous");
jQuery(this.holder).append(previous);
}
if(index+i<this.data.length){
var next = jQuery("<a style='float:right;'>").attr("href","#").click(this.nextHandler).text("next >");
jQuery(this.holder).append(next);
}
}
,nextHandler: function() {
pagedContent.show(pagedContent.currentIndex + 5);
return false;
}
,previousHandler: function() {
pagedContent.show(pagedContent.currentIndex - 5);
return false
}
};
I call the function like this
pagedContent.init(json.users.locations, 'div#secondList');
The json looks like this
{"locations" : [ {"id":"21319","name":"Naugatuck American Legion","city":"Ansonia","region":"Connecticut"},{"id":"26614","name":"Studio B789","city":"Acton","region":"Maine"},{"id":"26674","name":"Deering Grange Hall","city":"Bailey Island","region":"Maine"},{"id":"27554","name":"Accu Billiards","city":"Acushnet","region":"Massachusetts"}]}
I may have found the problem with your code:
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
(...)
When you call show(0) you set index to 0. You expect a fixed number of items in the array (5 in the range [0..4]) but there are only 4 locations in your data.
If you are using console.log to trace the problems in firebug you might find that it is a problem with firebug. Try just running console.log on it's own.
If it is a problem with firebug try updating it. There are some development versions around which might fix the problem.
I had a similar problem and fixed it by doing the above.