I have a function that defines a variable and I would like to use the value in the next function. Each function has it's own query. I think I either need to combine the queries into one function, of which I don't know how to do or setup a global variable with the first query so it can be referenced in the second function.
I've been reading that global variables and they say they're not a good practice. Can someone help me with how to reuse a variable from one function to the next or combine the two queries else another JS method I should consider?
google.setOnLoadCallback(queryValue1);
function queryValue1 () {
var query2 = new google.visualization.Query('https://spreadsheets.google.com/spreadsheet/tq?range=A2:A17&key=0AhCv9Xu_eRnSdFNhSzNQUFd3b1ZfRHgtQURINFpzeGc&gid=9');
query2.send(function (response) {
if (response.isError()) {
alert('Error in query2: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data1 = response.getDataTable();
// fetch the data from range cell (row, column) into the span "bx"
for (var z = 0; z <= 15; z++) {
document.getElementById('a' + (z + 22)).innerHTML = data1.getValue(z, 0);
}
});
}
google.setOnLoadCallback(queryValue3);
function queryValue3 () {
var query3 = new google.visualization.Query('https://spreadsheets.google.com/spreadsheet/tq?range=B2:B17&key=0AhCv9Xu_eRnSdFNhSzNQUFd3b1ZfRHgtQURINFpzeGc&gid=10');
query3.send(function (response) {
if (response.isError()) {
alert('Error in query3: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data3 = response.getDataTable();
var m1 = data3.getValue(0, 0);
var red22 = "<span style='color:#ff0000' ";
var yellow22 = "<span style='color:#FF9900' ";
var green22 = "<span style='color:#009900' ";
if (m1 <= 70)
{
m1 = red22;
}
else if (71 === m1 && m1 <= 89)
{
m1 = yellow22;
}
else if (m1 >=90)
{
m1 = green22;
}
console.log ("m1= " + m1)
var m1 = (m1 + a22 + "</span>");
console.log ("m1= " + m1)
});
}
Thank you...
As it is, your making two essentially parallel asynchronous network calls (the Query.send() calls). There's no telling which one is going to return first (or if one will fail), so relying in one callback on data from the other is unreliable and a bad idea, no matter whether you use a global variable or something else.
I think you probably just want to chain the two asynchronous calls, so try something of this shape:
google.setOnLoadCallback(queryValue1);
function queryValue1 () {
var query2 = new google.visualization.Query('https://spreadsheets.google.com/spreadsheet/tq?range=A2:A17&key=0AhCv9Xu_eRnSdFNhSzNQUFd3b1ZfRHgtQURINFpzeGc&gid=9');
query2.send(function (response) {
if (response.isError()) {
alert('Error in query2: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
// Get the data you want to pass to query3 here
// var query3Data = ...
queryValue3(query3Data);
});
}
function queryValue3(passedData) {
var query3 = new google.visualization.Query('https://spreadsheets.google.com/spreadsheet/tq?range=B2:B17&key=0AhCv9Xu_eRnSdFNhSzNQUFd3b1ZfRHgtQURINFpzeGc&gid=10');
query3.send(function (response) {
if (response.isError()) {
alert('Error in query3: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
// Do something with passedData here
// ...
});
}
So don't start the second query until the first one returned.
Related
because I tried query 3 sheets with 3 charts at the same time with 1 handle function ,it works but the result is wrong (it display the same chart in 3 div)
So I think I have to add handle function on each chart like
google.charts.load('current', {packages: ["geochart"]});
google.charts.setOnLoadCallback(drawRegionsMap);
function drawRegionsMap() {
var query1 = new google.visualization.Query("https://docs.google.com/spreadsheets/d/14VouG7zZqHGB9CA6bxQx6CXX-TvOYkSqTmrN5DAj1Do/edit#gid=1175123524");
var query2 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1RsugJPtz2EdHOLaiL0SvR9bh61H-vAgn9x1QBjIJ--c/edit?usp=sharing');
var query3 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1zPP22gUPLDqTrvASIU3OXpmeHL_9IBS2O4z75g-1BHY/edit?usp=sharing');
query1.send(handleQueryResponseTR1);
query2.send(handleQueryResponseTR2);
query3.send(handleQueryResponseTR3);
}
function handleQueryResponseTR1(response1) {
if (response1.isError()) {
alert('Error in query: ' + response1.getMessage() + ' ' + response1.getDetailedMessage());
return;
}
function handleQueryResponseTR2(response2) {
if (response2.isError()) {
alert('Error in query: ' + response2.getMessage() + ' ' + response2.getDetailedMessage());
return;
}
function handleQueryResponseTR3(response3) {
if (response3.isError()) {
alert('Error in query: ' + response3.getMessage() + ' ' + response3.getDetailedMessage());
return;
}
var data1 = response1.getDataTable();
var data2 = response2.getDataTable();
var data3 = response3.getDataTable();
but I got an error
handleQueryResponseTR2 is not defined
So I don't know if google chart can query more than 1 sheet in one page?
I don't believe googlechart queries have any problems with multiple queries at the same time, to answer the question.
Regarding your code:
Your handleQueryResponseTR2 function is a local function in handleQueryResponseTR1 but you try to call it from drawRegionsMap(). handleQueryResponseTR2() is not defined in that scope.
Move handleQueryResponseTR2() to upper scope to make it visible to the calling function.
In fact, move all your handleQueryResponse functions to the upper level.
var data1;
var data2;
var data3;
function handleQueryResponseTR1(response1) {
if (response1.isError()) {
alert('Error in query: ' + response1.getMessage() + ' ' + response1.getDetailedMessage());
return;
}
data1 = response1.getDataTable();
}
function handleQueryResponseTR2(response2) {
if (response2.isError()) {
alert('Error in query: ' + response2.getMessage() + ' ' + response2.getDetailedMessage());
return;
}
data2 = response2.getDataTable();
}
function handleQueryResponseTR3(response3) {
if (response3.isError()) {
alert('Error in query: ' + response3.getMessage() + ' ' + response3.getDetailedMessage());
return;
}
data3 = response3.getDataTable();
}
function drawRegionsMap() {
var query1 = new google.visualization.Query("https://docs.google.com/spreadsheets/d/14VouG7zZqHGB9CA6bxQx6CXX-TvOYkSqTmrN5DAj1Do/edit#gid=1175123524");
var query2 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1RsugJPtz2EdHOLaiL0SvR9bh61H-vAgn9x1QBjIJ--c/edit?usp=sharing');
var query3 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1zPP22gUPLDqTrvASIU3OXpmeHL_9IBS2O4z75g-1BHY/edit?usp=sharing');
query1.send(handleQueryResponseTR1);
query2.send(handleQueryResponseTR2);
query3.send(handleQueryResponseTR3);
}
Please, note that the handleQueryResponse functions are called asynchronously when the responses are received.
The problem I have is that all the json we pass over come from python, and we can't send over javascript in such things. For instance', I need to include the tech from this question but obviously in the plotOptions. I'm just not sure how to do things like reference series, etc. So an example with the above series would be great. I tried the following but it didn't work since this is not what I expected it to be.
options.plotOptions = options.plotOptions || {};
options.plotOptions.series = options.plotOptions.series || {};
options.plotOptions.series.point =
options.plotOptions.series.point || {};
options.plotOptions.series.point.events =
options.plotOptions.series.point.events || {};
options.plotOptions.tooltip = {formatter: function() {
var text = '';
if(this.series.name == 'MSFT') {
text = this.x + ': ' + this.series.name +
'<br> $' + Highcharts.numberFormat(this.y, 0);
} else {
text = 'In ' + this.x + ' the median value was' + this.median +
'and the total $' + Highcharts.numberFormat(this.y, 0);
}
return text;
}
options.plotOptions.series.point.events.click = function() {
if (this.options.url){
window.open(this.options.url);
}
}
I am currently writing some tests against the code shown below in node.js using mocha. I want to simulate the response from the event emitter 'check_user'. I have sinon.js but I can't get my mind in the right place to work out the best way to simulate the response.
Anyone able to offer some advice on how to go about this?
TgCustomCommand.contact = new Command("contact", "Will send you a users contact card to add to your contact list. Usage is .contact nick", function (input, callback) {
var payload = input;
//Switch our contact to payload.to as this is what our checkuser function looks at
//Check the command over
if (payload.command_args === false) {
payload.response = 'msg ' + payload.to + ' ' + this.description;
return callback(null, payload);
} else {
payload.return = payload.to;
payload.to = payload.command_args; //Set up ready for nick check
//Check the nick exists
emitter.emit('check_user', payload, function (err, result) {
if (err) return callback(err, null);
payload = input; //Reset our payload so we have correct payload.to
//Check how many users we returned
if (result.length === 0) { //Not in our contact list
payload.response = 'msg ' + payload.return + ' I do not have that person in my contact list!';
return callback(null, payload);
} else if (result.length === 1) {
payload.to = result[0].Nick;
payload.response = "send_contact " + payload.return + ' ' + result[0].Phone + ' ' + result[0].Nick + " _";
return callback(null, payload);
}
else {
//loop through our object and create a list of those returned
payload.response = "msg " + payload.return + " I know multiple people with a similar nick: ";
for (var i = 0; i < result.length; i++) {
log.debug(result[i].Nick);
payload.response = payload.response + result[i].Nick + " ";
}
return callback(null, payload);
}
});
}
;
});
I want my context menu item to be visible only if the clicked node is a link i.e. and href is either a magnet link or a torrent link. But item is visible for all the links because context function is not executing, can anybody help why context function is not executing?
Here is the code:
exports.main = function() {
var cm = require("sdk/context-menu");
var contextCode = ' self.on("context", function (node) { '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_magnet = /^magnet:/i; ' +
' var pat_torrent = /.torrent$/i; ' +
' if(pat_torrent.test(node.href) || pat_magnet.test(node.href)) { return true; } '+
' else { return false; } '+
' }); ';
var clickCode = ' self.on("click", function(node,data){ '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_hash = /[0-9abcdef]{32,40}/i; ' +
' var result = node.href.match(pat_hash); '+
' var hash = "" '
' if(result != null) { hash=result[0]; } '+
' var xhr = new XMLHttpRequest(); '+
' if(hash != "") { '+
' var apiCall = "https://www.furk.net/api/dl/add?api_key=*************&info_hash="+hash; '+
' } '+
' else{ '+
' var apiCall = "https://www.furk.net/api/dl/add?api_key=*************&url="+encodeURI(node.href); '+
' } '+
' xhr.open("GET",apiCall,true); '+
' xhr.onreadystatechange = function(){ if(xhr.readyState = 4) { if (xhr.response.status = "ok") { alert("Torrent added to Furk."); } else { alert("Torrent could not be added to Furk."); } } } '+
' xhr.send(null); '+
' });';
cm.Item({
label: "Add to Furk",
context: cm.SelectorContext("a[href]"),
contentScript: contextCode + clickCode
});
};
Please always post self-containied examples that can be directly tried in the future.
Now back to your problem: The content script actually has a syntax error.
The following line:
' var pat_torrent = /.torrent$/i ' +
lacks a semicolon, and should be:
' var pat_torrent = /.torrent$/i; ' +
The reason automatic semicolon insertion (ASI) does not work here is: The "code" is actually a string that has no newlines in it whatsoever. If there were newlines, then ASI would have worked.
Anway, another reason not to have complex content script inline. Have a look at contentScriptFile.
This error is actually logged, but the presentation sucks. In the Browser Console:
[20:57:51.707] [object Error] (expandable)
In terminal:
console.error: context-magnet:
Message: SyntaxError: missing ; before statement
Here is a fixed, reproducible sample:
var cm = require("sdk/context-menu");
var contextCode = ' self.on("context", function (node) { '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_magnet = /^magnet:/i; ' +
' var pat_torrent = /.torrent$/i; ' +
' if(pat_torrent.test(node.href) || pat_magnet.test(node.href)) { return true; } '+
' else { return false; } '+
' }); ';
cm.Item({
label: "magnet test",
context: cm.SelectorContext("a[href]"),
contentScript: contextCode
});
Edit ' var hash = "" ' has the same problem, and there are might be other such errors that I missed skimming this new code.
As I already said, please use contentScriptFile and not contentScript for long-ish scripts.
Another edit
Here is a builder using contentScriptFile, where I also fixed a couple of other errors, the most important of which are:
Use permissions so that the XHR will work.
Correctly set up the XHR to use responseType and overrideMimeType().
Use onload/onerror instead of onreadystatechange.
I am trying to insert around 58000 rows of a query inside a string. But after the row around 8000 I get a timeout error.
I've already tried to use SetTimeout funcions but it was of no use.
Check the code that I am working on:
function onQuerySuccess(tx, results) {
console.log("Entering onQuerySuccess");
if(results.rows) {
console.log("Rows: " + results.rows.length);
var len = results.rows.length;
if(len > 0) {
store_html(results, 0);
console.log("Finished Reading Rows: " + len);
saveNotes();
console.log("Finished Saving Notes");
} else {
//This should never happen
console.log("No rows.");
}
} else {
alert("No records match selection criteria.");
}
console.log("Leaving openView");
function store_html(results, rows_complete){
rows_complete=store_html_input(results, rows_complete);
console.log("Returning row:" + rows_complete);
if (rows_complete<results.rows.length)
{
setTimeout(store_html(results, rows_complete), 50);
}
}
function store_html_input(results, rows_complete){
for(var i = rows_complete; i < rows_complete+100; i++) {
gpsTextFile = gpsTextFile + results.rows.item(i).section + ' ' + results.rows.item(i).timestamp + ' ' + results.rows.item(i).latitude + ' ' +
results.rows.item(i).longitude + ' ' + results.rows.item(i).acx + ' ' + results.rows.item(i).acy + ' ' +
results.rows.item(i).acz + ' ' + results.rows.item(i).speed;
gpsTextFile = gpsTextFile + "\n\r";
}
return i;
}
So.. I get that "Javascript execution exceeded timeout".
Thank you for any of your help!
Best Regards.
You need to change your setTimeout() to NOT execute the function immediately. Change from this:
setTimeout(store_html(results, rows_complete), 50);
to this:
setTimeout(function() {store_html(results, rows_complete)}, 50);
As you had it before, it was immediately executing store_html(results, rows_complete) and passing the return value from that to `setTimeout() which was not delaying anything. This is a common mistake (2nd one of these problems I've answered today).