I am writing a game for Facebook. IN the following code, I have a problem. I have a for loop executing, and in that loop, I call a dialog and implement 'onconfirm' for the dialog. The problem is that I need to access th e loop counter inside of the onconfirm function. But because the onconfirm is called outside of the scope of the for loop, the counter value is no longer valid because it's been incremented. I need some way to pass the counter value to the dialog onconfirm as it was at the time the dialog was displayed, not after the loop has finished. Or maybe someone has a better solution. Any help would be appreciated. Thanks.
function unloadCargo() {
//debugger;
var actionPrompt = document.getElementById('action-prompt');
actionPrompt.setTextValue('Unloading cargo...');
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data) {
debugger;
if(data.unloadableCargo.length == 0) {
loadCargo();
} else {
//console.log('unloadable cargo='+dump(data.unloadableCargo));
var i = 0;
var j = 0;
var ucCount = data.unloadableCargo.length;
for(i = 0; i < ucCount; i++) {
cargoDialog = new Dialog();
cargoDialog.showChoice('Unload Cargo', 'Unload ' + data.unloadableCargo[i].goods_name + ' at ' + data.unloadableCargo[i].city_name + ' for ' + data.unloadableCargo[i].payoff + 'M euros?');
cargoDialog.onconfirm = function() {
//console.log('unloadable cargo onconfirm='+dump(data.unloadableCargo));
var ajax = new Ajax();
var param = {"city_id": data.unloadableCargo[i].city_id, "goods_id": data.unloadableCargo[i].goods_id, "payoff": data.unloadableCargo[i].payoff};
ajax.ondone = function(demandData) {
var demands = document.getElementById('demands');
var innerXhtml = '<span>';
for(var j = 0; j < demandData.demands.length; j++) {
innerXhtml = innerXhtml + ' <div class="demand-item"><div class="demand-city">' + demandData.demands[j].city + '</div><div class="demand-pay">' + demandData.demands[j].cost + '</div><div class="demand-goods">' + demandData.demands[j].goods + '</div></div>';
}
innerXtml = innerXhtml + ' </span>';
demands.setInnerXHTML(innerXhtml);
// update balance
loadCargo();
}
ajax.post(baseURL + "/turn/do-unload-cargo", param);
}
cargoDialog.oncancel = function() { loadCargo(); }
}
//loadCargo();
}
}
ajax.post(baseURL + '/turn/unload-cargo');
}
You need to pass the value to the dialog somehow.
I have never looked at the FBJS, but it seems setContext can be used for that.
Try this:
cargoDialog = new Dialog().setContext({currentIndex: i});
// showChoice is the same
cargoDialog.onconfirm = function() {
alert(this.currentIndex); // Here you should be able to get it
}
Related
This question already has answers here:
Refresh data retrieved by a custom function in Google Sheet
(21 answers)
Closed 9 months ago.
I have ImportJson() function that doesn't update its value unless I make changes to Appscript then reload the sheet again, I think it was running but suddenly stopped.
The function should be get the value of 'A2' if found go to the loop, if not just return the fixed API call data, but whatever I update the A2 cell it doesn;t recall the function with the other kinds of the API call but it runs normally in the app script editor
function ImportData1() {
var Final_result = [];
var VenueId_results = [];
var PageNumber_index = 0;
var Page_number = [0, 1, 2, 3, 4];
var New_URL = "";
var url = "https://app.ticketmaster.com/discovery/v2/events?sort=venueName,asc&locale=*&size=199&" + "page=" + Page_number[PageNumber_index] + "&apikey=" + API_key + "&venueId=" + venueIds;
// ImportJSON(url, "/","noInherit,noTruncate,rawHeaders");
// console.log(ImportJSON(url, "/", "noInherit,noTruncate,rawHeaders"));
// console.log("Veuneid" + Veunue_id + Venue_Id_List.length);
console.log("ImportData1();" + Venue_Id_List.length);
var New_Venue = SpreadsheetApp.getActiveSheet().getRange('A2').getValue();
console.log(New_Venue);
if ( New_Venue != "") {
var Venue_arr = New_Venue.split(",");
VenueId_results = Add_new_VeunueId(Venue_arr);
var Last_New_Id_Venue = "";
for (var Index_venune = 2; Index_venune < (VenueId_results.length) - 2; Index_venune++) {
console.log("Venuesid " + VenueId_results[Index_venune]);
var New_Id_Venue = VenueId_results[Index_venune].toString() + ",";
Last_New_Id_Venue += New_Id_Venue;
console.log("New_Id_Venue " + New_Id_Venue);
}
console.log("Last_New_Id_Venue " + Last_New_Id_Venue);
New_URL = url + Last_New_Id_Venue;
New_Venue = "";
VenueId_results = [];
// return ImportJSON(New_URL, "/_embedded/events/name,/_embedded/events/url,/_embedded/events/_embedded/venues/name,/_embedded/events/dates/start/localDate,/_embedded/events/dates/start/dateTime,/_embedded/events/priceRanges/min,/_embedded/events/priceRanges/max,/_embedded/events/_embedded/venues/url,/_embedded/events/_embedded/venues/city/name", "noInherit,noTruncate,rawHeaders");
for (; PageNumber_index < Page_number.length; PageNumber_index++) {
console.log("looopsyes");
Final_result = Final_result.concat(ImportJSON(New_URL, "/_embedded/events/name,/_embedded/events/url,/_embedded/events/_embedded/venues/name,/_embedded/events/dates/start/localDate,/_embedded/events/dates/start/dateTime,/_embedded/events/priceRanges/min,/_embedded/events/priceRanges/max,/_embedded/events/_embedded/venues/url,/_embedded/events/_embedded/venues/city/name", "noInherit,noTruncate,rawHeaders"));
console.log("New_URL " + PageNumber_index + Page_number[PageNumber_index] + Final_result);
Utilities.sleep(1000);
}
console.log("New_URL " + New_URL);
console.log("Final_result " + Final_result);
return Final_result;
console.log("New_URL " + Page_number);
return Final_result;
// url += New_Venue;
var New_URL = url + New_Venue;
console.log("hello" + New_URL);
} else {
console.log("hellono");
New_Venue = "";
VenueId_results = [];
return ImportJSON(url, "/_embedded/events/name,/_embedded/events/url,/_embedded/events/_embedded/venues/name,/_embedded/events/dates/start/localDate,/_embedded/events/dates/start/dateTime,/_embedded/events/priceRanges/min,/_embedded/events/priceRanges/max,/_embedded/events/_embedded/venues/url,/_embedded/events/_embedded/venues/city/name", "noInherit,noTruncate,rawHeaders");
}
// /_embedded/events/name,/_embedded/events/url,/_embedded/events/dates/start/localDate,/_embedded/events/dates/start/dateTime,/_embedded/events/priceRanges/min,/_embedded/events/priceRanges/max,/_embedded/events/_embedded/venues/name,/_embedded/events/_embedded/venues/url,/_embedded/events/_embedded/venues/city/name
// setTimeout(import_data, 5000);
}
Here is a simple function that you can setup to trigger every time cell A2 changes. It will call your import function when the right cell has changed.
function valueChange(e)
{
if (e.range.getRow() == 1 && e.range.getColumn() == 2)
{
ImportData1();
}
}
I'm experiencing some weird behavior in my code that I don't quite understand. I call a function, and inside that function there is another (anonymous) callback function it skips over and it goes to the end of the containing function, runs those lines, and then goes back into the callback function and runs those lines... Anybody have some insight, what am I doing wrong? Is it doing this because the "relatedQuery" method isn't complete yet so it hasn't hit the callback function before it runs the rest of the containing function's lines? That's the only thing I can think of, but I'm also not very skilled at JS. I've added some console.log statements that will tell you the order in which lines are being hit.
//Call the mgmtPopupContent function
mgmtTractPopupBox.setContent(mgmtPopupContent);
function mgmtPopupContent(feature) {
for (var attrb in feature.attributes) {
if (attrb == "HabitatManagement.DBO.MgmtTracts.OBJECTID") {
var OID = feature.attributes[attrb];
}
}
var relatedQuery = new RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0;
relatedQuery.objectIds = [OID];
//Get data year that the map view is set to and set the definition expression on the table
viewYear = dom.byId("data-year").value;
relatedQuery.definitionExpression = "YearTreated = " + viewYear;
//Create table header that will go inside popup
var content = '<table id="mgmtPopupTable1"><tr><th>Veg Mgmt Practice</th><th>Herbicide</th><th>Month</th><th>Year</th>\
<th>Implemented By</th><th>Funded By</th><th>Farm Bill Code</th></tr>';
console.log("PRINTS FIRST");
//Do query and get the attributes of each related record for the popup
queryableMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
console.log("PRINTS THIRD");
var fset = relatedRecords[OID].features;
fset.forEach(function (feature) {
var vegPractice = vegPName(feature.attributes.VegMgmtPractice);
var herbicide = herbName(feature.attributes.Herbicide);
var monthTreated = monthName(feature.attributes.MonthTreated);
var yearTreated = feature.attributes.YearTreated;
var impBy = impName(feature.attributes.ImplementedBy);
var fundBy = fundName(feature.attributes.FundedBy);
var fbc = feature.attributes.FarmBillCode;
if (fundBy == "CRP" || fundBy == "CRP - CREP") {
fbc = crpName(fbc);
}
else if (fundBy == "EQIP" || fundBy == "EQIP - RCPP") {
fbc = eqipName(fbc);
}
else {
fbc = "Not applicable";
}
row = '<tr><td>' + vegPractice + '</td><td>' + herbicide + '</td><td>' + monthTreated + '</td><td>' + yearTreated +
'</td><td>' + impBy + '</td><td>' + fundBy + '</td><td>' + fbc + '</td></tr>';
content = content + row;
});
content = content + '</table>';
});
console.log("PRINTS SECOND");
return content;
}
As mentioned in my comment, you have to wait for the queries to finish before you can render the content. So something like:
let content = '<table id="mgmtPopupTable1"><tr><th>Veg Mgmt Practice</th><th>Herbicide</th><th>Month</th><th>Year</th>\
<th>Implemented By</th><th>Funded By</th><th>Farm Bill Code</th></tr>';
const render_popup = function( content ) {
document.querySelector( '#myPopup' ).innerHTML = content;
};
// Render only the headers to begin with.
render_popup( content );
queryableMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
var fset = relatedRecords[OID].features;
fset.forEach(function (feature) {
...
});
// Rerender the popup, now headers And content.
render_popup( content );
});
Assign value to global tracking variable on submit of form.
var tracking;
$('.form-inline').submit(function (e) {
e.preventDefault();
tracking = jQuery('input[name="tracking"]').val();
init()
})
execute function init()
function init() {
Tabletop.init({
key: public_spreadsheet_url,
callback: showInfo,
simpleSheet: true
})
}
Which initiates the showInfo callback
var zipMatches = "";
function showInfo(data, tabletop) {
alert('Callback initiated..');
for (var i = 0; i < data.length; i++) {
var myRegex = '/' + tracking + '/';
console.log(myRegex)
if (myRegex.test(data[i].tracking)) {
zipMatches = zipMatches + data[i].location_1 + ", " + data[i].location_2 + ", " + data[i].location_3;
}
}
//write it into the DOM
var myElement = document.querySelector(".myJSON");
myElement.innerHTML = "<h3>List of Zipcodes that match tracking ID: </h3><p>" + zipMatches + "</p>";
}
myRegex.test is not a function
However regex function works with hardcoded value
if (/ABCD123/.test(data[i].tracking)) {...
How do I pass the regex value as a global variable?
..
Edit (working callback function):
function showInfo(data, tabletop) {
var regexp = new RegExp(tracking);
for (var i = 0; i < data.length; i++) {
if (regexp.test(data[i].tracking)) {
zipMatches = zipMatches + data[i].location_1 + ", " + data[i].location_2 + ", " + data[i].location_3;
}
}..
Plese try with following sol:
var regexp = new RegExp(tracking);
and please put it outside of forloop. So it is optimized.
Since you have tried
var regexp = "/" + tracking + "/"; will convert it into string. Not regex object. So you won't get test method in it.
Hope it helps :)
I am trying to create a simple chrome extension. When a user clicks a checkbox a few datas are send to the background script and from there to the popup. The data is transmitted successfully and it is stored in localstorage at popup
$(document).ready(function() {
chrome.runtime.sendMessage({
from: 'popup',
subject: 'getmessage',
}, function(response) {
for (var x = 0; x < JSON.parse(response).length; x++) {
localStorage.setItem(JSON.parse(response)[x].acnumber, JSON.stringify(JSON.parse(response)[x]));
}
});
for (var i = 0, len = localStorage.length; i < len; i++) {
var datas = JSON.parse(localStorage.getItem(localStorage.key(i)));
var value = datas;
console.log(value);
$('table').append('<tr class="' + value.acnumber + '"><td>' + value.acnumber + '</td><td>' + value.name + '</td><td>' + value.amount + '</td></tr>')
}
})
The problem is that i have to open the popup twice to see the data (appended to the table). The loop is executing before the datas are added to the localstorage
You'll need to move the append table code inside the response function if you want to process the data right after the response callback is fired. Since you mentioned you need the data on multiple pages, you can move the chrome.runtime.sendMessage in its own function and call it only if you don't already have the data. Something like
function getMessage() {
chrome.runtime.sendMessage({
from: 'popup',
subject: 'getmessage',
}, function(response) {
localStorage['haveMessage'] = true;
for (var x = 0; x < JSON.parse(response).length; x++) {
localStorage.setItem(JSON.parse(response)[x].acnumber, JSON.stringify(JSON.parse(response)[x]));
}
processMessage();
});
}
function processMessage() {
for (var i = 0, len = localStorage.length; i < len; i++) {
var datas = JSON.parse(localStorage.getItem(localStorage.key(i)));
var value = datas;
console.log(value);
$('table').append('<tr class="' + value.acnumber + '"><td>' + value.acnumber + '</td><td>' + value.name + '</td><td>' + value.amount + '</td></tr>')
}
}
if (locaStorage['haveMessage']) {
processMessage();
} else {
getMessage();
}
I've been doing web development for quite sometime and have never seen this behavior with JavaScript. This is the code I started out with:
function processLogin() {
if (loginReq.readyState == 4) {
var data = eval('(' + loginReq.responseText + ')');
data = data.userData;
var focus = data.team.focus.coordinates;
thisTeam = new Team(data.team.id, data.team.missionId, data.team.name, data.team.operatingArea.coordinates[0]);
if (data.team.zoomLevel != '') {
thisTeam.zoomLevel = data.team.zoomLevel;
}
if (focus.length > 0) {
thisTeam.focusLat = focus[1];
thisTeam.focusLon = focus[0];
}
for (var i = 0; i < data.teams.length; i++) {
var temp_team = new Team(data.teams[i].id, data.teams[i].missionId, data.teams[i].name, []);
teams.push(temp_team);
}
var teamDropDownText = [];
for (var j = 0; j < teams.length; j++) {
if (thisTeam.teamId == teams[j].teamId) {
teamDropDownText.push('<option value="' + teams[j].teamId + '" selected="selected">' + teams[j].name + '</option>');
} else {
teamDropDownText.push('<option value="' + teams[j].teamId + '">' + teams[j].name + '</option>');
}
}
$('#addIncidentTeam').html(teamDropDownText.join(''));
$('#editIncidentTeam').html(teamDropDownText.join(''));
// When all this has finished, make the
// rest of the calls to get the rest of the data
startTimer();
downloadDevices();
initializeMap();
}
}
What I have written there isn't that important, and let me explain why.
The line with the single semicolon after thisTeam.zoomLevel = data.team.zoomLevel; was giving me a syntax error in firebug. I read and re-read my code, and couldn't figure out what I did wrong, so I put the semicolon on the same line as thisTeam.zoomLevel = data.team.zoomLevel and it told me it had a syntax error on the blank line!
To do another test, I moved this whole function to it's own JavaScript file and put everything after that line on one line and even tried to condense some of the code above, so now it looks like this:
function processLogin() {
if (loginReq.readyState == 4) {
var data = eval('(' + loginReq.responseText + ')');
data = data.userData;
var focus = data.team.focus.coordinates;
thisTeam = new Team(data.team.id, data.team.missionId, data.team.name, data.team.operatingArea.coordinates[0]); if (data.team.zoomLevel.length > 0) { thisTeam.zoomLevel = data.team.zoomLevel; } if (focus.length > 0) { thisTeam.focusLat = focus[1];thisTeam.focusLon = focus[0];} for (var i = 0; i < data.teams.length; i++) { var temp_team = new Team(data.teams[i].id, data.teams[i].missionId, data.teams[i].name, []); teams.push(temp_team); } var teamDropDownText = []; for (var j = 0; j < teams.length; j++) { if (thisTeam.teamId == teams[j].teamId) { teamDropDownText.push('<option value="' + teams[j].teamId + '" selected="selected">' + teams[j].name + '</option>'); } else { teamDropDownText.push('<option value="' + teams[j].teamId + '">' + teams[j].name + '</option>'); } } $('#addIncidentTeam').html(teamDropDownText.join('')); $('#editIncidentTeam').html(teamDropDownText.join('')); /* When all this has finished, make the rest of the calls to get the rest of the data */ startTimer(); downloadDevices(); initializeMap(); var kmlLink = document.getElementById('kmlLink'); var geoserverLink = document.getElementById('geoserverLink') if (user_role.substring(0, 1) == 'M') { kmlLink.href = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/M&" + thisTeam.missionId + "&48"; kmlLink.innerHTML = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/M&" + thisTeam.missionId + "&48"; geoserverLink.href = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=mission_id+=+" + thisTeam.missionId; geoserverLink.innerHTML = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=mission_id+=+" + thisTeam.missionId;} else { kmlLink.href = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/T&" + thisTeam.id + "&48"; kmlLink.innerHTML = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/T&" + thisTeam.id + "&48"; geoserverLink.href = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=team_id+=+" + thisTeam.id; geoserverLink.innerHTML = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=team_id+=+" + thisTeam.id; } } }
I did this just to see what error I would get, I knew it wouldn't work correctly. But now it's telling me there's an error on a line that doesn't exist in the file! I get:
syntax error
[Break On This Error] (10 out of range 8)
I went and commented more code out and it just made it 10 out of range 6! I don't understand!
I found the culprit. One of the values of the JSON returned was empty (no quotes or anything). Not a very helpful error message.