Populating html table with slowly loading separate jquery fuctions - javascript

I've seen many topics like this, some with pretty much the exact same title, but I'm still not finding a solution for what I'm attempting.
I basically have an HTML table that is getting data from 10 different sources. 9 of the sources I'm trying to push to an array and fund the sum, which will be one column in the table. And the other source is just a single external query result.
I'm running into problems when they take too long to load and the table has already populated.
I tried a timeout function but it doesn't seem to work even then. I'm also having issues with the table showing 10 commas separated values and not a sum, even when I add a variable =0 and then do source1+= variable for each of the sources.
Heres what I have so far, I Some of the letterers in the code are just random and a placeholder to show the structure. But this is the basic setup. I've only included 2 out of the 9 functions to save space, but its pretty much similar to the first two, 3..4..5 etc.
At a loss here, any help would be awesome and I thank you all for your valuable time.
/* HTML */
<table id="AA"> <caption>title<span id="totalValue">0</span></caption>
<tr>
<th>L</th>
<th>L Qty.</th>
<th>W</th>
<th class="value">Value</th>
<th>some text</th>
<label for="CD">
</label>
<input id="img" type="hidden" value="somedatahere" size="60" />
</tr>
</table>
//and heres the separate js
var sumqholder = 0;
$('#Form').submit(function(event) {
event.preventDefault();
$('#results').html('loading...');
var AB = $('#CD').val();
A.H.call(function(err, J) {
A.I.call(function(err, K) {
var EF = $('#EF').val();
A.G.call(EF, function(err, G) {
var results = '<b>--:</b> ';
results += G.round(5);
sumq += G;
$('#results').html(results);
});
});
$('#results2').html('loading...');
var AB = $('#CD').val();
A.H.call(function(err, J) {
A.I.call(function(err, K) {
var EF = $('#EF').val();
A.G.call(IA, function(err, G) {
var results2 = '<b>--:</b> ';
results2 += G.round(5);
sumq += G;
$('#results2').html(results2);
});
});
var sumq = sumqholder;
var L = [{
M: O,
quantity: sumq
}, {
P: " ",
quantity: x
}];
var totalValue = 0;
$(document).ready(function() {
refresh();
});
function refresh() {
$("#AA").find("tr:gt(0)").remove();
totalValue = 0;
L.forEach(function(L) {
sendRequest(L.M, L.quantity);
});
}
function sendRequest(M, L) {
var url = " " + M + "/";
$.get(url, function(data) {
addRow(data[0], quantity);
});
}
function addRow(data, quantity) {
var value = data.W * quantity;
totalValue += value;
var row = '<tr>';
row += '<td>' + data.I + '</td>';
row += '<td>' + quantity + '</td>';
row += '<td>' + data.I + '</td>';
row += '<td>' + value.toFixed(2) + '</td>';
row += '<td>' + data.O + '</td>';
row += '</tr>';
$('#AA tr:last').after(row);
updateTotalValue();
}
function updateTotalValue() {
$("#totalValue").text(totalValue.toFixed(6));
}

If i got this right, you're having problems processing data because the source is coming from 10 different async calls right? If that's the case, have each call finish off by calling a checking function.
var flag = 0;
function checkLoaded()
{
if(flag == 9){
doDataProcessing();
}else{
flag++;
}
}
This way, each call will end calling checkLoaded(); and if its the 10th one, flag will have incremented 9 times therefore we can already assume we can proceed to data processing.

This is precisely the kind of scenario that promises were designed to simplify. They will help you avoid "callback hell" and manage errors.
First, with reference to How do I Convert an Existing Callback API to Promises?, promisify all methods that accept a callback :
A.G.callAsync = function(val) {
return new Promise(function(resolve, reject) {
A.G.call(val, function(err, x) {
err ? reject(err) : resolve(x);
});
});
};
A.H.callAsync = function() {
return new Promise(function(resolve, reject) {
A.H.call(function(err, x) {
err ? reject(err) : resolve(x);
});
});
};
A.I.callAsync = function() {
return new Promise(function(resolve, reject) {
A.I.call(function(err, x) {
err ? reject(err) : resolve(x);
});
});
};
jQuery's $.get() already returns a promise therefore doesn't need to be promisified.
Then, everything else can be done inside a $(document).ready(function() {...}) structure, something like this :
$(document).ready(function() {
$('#Form').submit(function (event) {
event.preventDefault();
$('#results').html('loading...');
// promise chain for the first A.H(), A.I(), A,G() sequence.
var promise1 = A.H.callAsync().then(function(J) {
return A.I.callAsync();
}).then(function(K) {
return A.G.callAsync($('#AB').val());
}).then(function(G) {
$('#results').html('<b>--:</b> ' + G.round(5));
return G; // the chain delivers this value
});
// promise chain for the second A.H(), A.I(), A,G() sequence.
var promise2 = promise1.then(function() {
$('#results2').html('loading...');
return A.H.callAsync().then(function(J) {
return A.I.callAsync();
}).then(function(K) {
return A.G.callAsync($('#EF').val());
}).then(function(G) {
$('#results2').html('<b>--:</b> ' + G.round(5));
return G; // the chain delivers this value
});
});
Promise.all([promise1, promise2]) // aggregate promise1 and promise2
.then(function(G_values) { // G_values is an array containing the `G` values delivered by promise1 and promise2.
var sumq = G_values.reduce(function(runningTotal, val) {
return runningTotal + val;
}, 0);
var L = [
{ 'M': O, 'quantity': sumq }, // what is O?
{ 'P': ' ', 'quantity': x } // where's 'M'? what is 'x'
// ...
];
$("#AA").find("tr:gt(0)").remove();
return Promise.all(L.map(sendRequest)) // aggregate all the promises returned by sendRequest()
.then(function(values) { // `values` is an array of values delivered by the promises returned from sendRequest().
var totalValue = values.reduce(function(runningTotal, val) {
return runningTotal + val;
}, 0); // ie values[0] + values[1] + ...
$("#totalValue").text(totalValue.toFixed(6));
});
function sendRequest(item) {
var url = ' ' + item.M + '/';
var $tr = $('<tr/>').insertAfter('#AA tr:last'); // inserting here ensures the <tr>s are in the same order as the objects in `L`.
return $.get(url)
.then(function(data) {
return addRow(data[0], item.quantity, $tr); // deliver addRow's return value to Promise.all() above
});
}
function addRow(data, quantity, $tr) {
var value = data.W * quantity;
var cells = '<td>' + data.I + '</td>'
+ '<td>' + quantity + '</td>'
+ '<td>' + data.I + '</td>'
+ '<td>' + value.toFixed(2) + '</td>'
+ '<td>' + data.O + '</td>';
$tr.html(cells);
return value; // for on-screen consistency, you may choose to `return Number(value.toFixed(2))`
}
}).catch(function(err) {
console.error(err);
});
});
});
I'm not sure that's 100% what you want but it should give you a good idea how to solve an asynchronous javascript problem.

Related

How to use higher order functions instead of FOR Loop for Line items in Suitelet printouts (Netsuite)?

i have been tasked by my senior to print values of line items using higher order functions (.filter/.map/.reject/.reduce). I m confused how to write the higher order function instead of a for loop(for printing the line values in Invoice Printout). I need to print the line only when the qty is more than 3. I m an intern and i dont know how it will work, kindly help.
Link to The code snippet: https://drive.google.com/file/d/1uVQQb0dsg_bo53fT3vk9f0G8WwZomgQg/view?usp=sharing
I always used if condition for printing the row only when the quantity field has value more than 3. I even know how to .filter but i dont know how to call it and where to call it. Please help
I don't believe Array.from works in server side code. If it does then use that. What I have been using are the following functions. They don't conform to the higher order functions specified but they work with Netsuite syntax and go a long way towards simplifying sublist handling and encapsulating code:
//SS2.x
//I have this as a snippet that can be included in server side scripts
function iter(rec, listName, cb){
var lim = rec.getLineCount({sublistId:listName});
var i = 0;
var getV = function (fld){
return rec.getSublistValue({sublistId:listName, fieldId:fld, line:i});
};
for(; i< lim; i++){
cb(i, getV);
}
}
// to use it:
iter(ctx.newRecord, 'item', function(idx, getV){
if(parseInt(getV('quantity')) >3){
...
}
});
or for SS1 scripts I have the following which allows code to be shared between UserEvent and Scheduled scripts or Suitelets
function forRecordLines(rec, machName, op, doReverse) {
var i, pred, incr;
var getVal = rec ? function(fld) {
return rec.getLineItemValue(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemValue(machName, fld, i);
};
var getText = rec ? function(fld) {
return rec.getLineItemText(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemText(machName, fld, i);
};
var setVal = rec ? function(fld, val) {
rec.setLineItemValue(machName, fld, i, val);
} : function(fld, val) {
nlapiSetLineItemValue(machName, fld, i, val);
};
var machCount = rec ? rec.getLineItemCount(machName) : nlapiGetLineItemCount(machName);
if(!doReverse){
i = 1;
pred = function(){ return i<= machCount;};
incr = function(){ i++;};
}else{
i = machCount;
pred = function(){ return i>0;};
incr = function(){ i--;};
}
while(pred()){
var ret = op(i, getVal, getText, setVal);
incr();
if (typeof ret != 'undefined' && !ret) break;
}
}
// User Event Script:
forRecordLines(null, 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
// in a Scheduled Script:
forRecordLines(nlapiLoadRecord('salesorder', id), 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
Usually its a straight forward task, but since you are getting length and based on that you are iterating, you can use Array.from. Its signature is:
Array.from(ArrayLikeObject, mapFunction);
var tableData = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var quantity = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return { item, description, quantity}
});
var htmlData = tableData.filter(...).map(getRowMarkup).join('');
function getRowMarkup(data) {
const { itemName, descript, quantity } = data;
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}
Or if you like to use more functional approach:
Create a function that reads and give you all data in Array format. You can use this data for any task.
Create a function that will accept an object of specified properties and returns a markup.
Pass the data to this markup after any filter condition.
Idea is to isolate both the task:
- Getting data that needs to be processed
- Presentation logic and style related code
var htmlString = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var qty = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return getRowMarkup(item, description, qty)
}).join('');
function getRowMarkup(itemName, descript, quantity) {
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}

Javascript initially skipping over nested function and then comes back to it?

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

Live Search from multiple JSON files, Javascript, AJAX

I have to implement a search bar using AJAX and jQuery that displays results from 3 JSON files. At the moment I have it working with one but I am not sure how I might adapt this to live search 3 separate JSON files simultaneously.
const search = document.querySelector('#search');
search.addEventListener('keydown', liveSearch);
function liveSearch() {
const searchField = search.value;
const myExp = new RegExp(searchField, "i");
$.getJSON('weekday.json', function(data) {
var output = '<ul>';
$.each(data, function(key, val) {
if ((val.Title.search(myExp) !== -1) || (val.Description.search(myExp) !== -1)) {
output += '<li>';
output += '<strong>' + val.Title + '</strong>';
output += '<p>' + val.Description + ' - ' + val.Price + '</p>';
output += '</li>';
}
});
output += '</ul>';
$('#output').html(output);
});
}
Any help would be appreciated.
you can use $.when to execute multiple async promise
```
$.when(
$.getJSON('weekday1.json'),
$.getJSON('weekday2.json'),
$.getJSON('weekday3.json')
).then(function (results) {
var r1 = results[0]; // result in weekday1.json
var r2 = results[1]; // result in weekday2.json
var r3 = results[2]; // result in weekday3.json
})
Note: the promise(.then function) will only be resolved after all async task are resolved.
Ref: https://api.jquery.com/jquery.when/
'results' in the code provided by arfai1213 does not return an array that can be used as suggested.
Splitting results as per the code below returns separate arrays that can be used.
$.when(
$.getJSON('./data/file1.json'),
$.getJSON('./data/file2.json')
).then(function (r1, r2) {
$.each(r1[0], function(key, val){
//do something
})
$.each(r2[0], function(key, val){
//do something
})
});

Returning data from my JavaScript function

I have been having issues getting the data I am requesting to display correctly it was being displayed as undefined.
fetch(url)
.then(res => res.json())
.then((manager) => {
/* console.log(manager); */
for (i in manager.data){
var row = $('<div id="Data">' + '<br>' + getLogo(manager, i) + '<br>'
+ '<br>' + '<p1>' + getName(manager, i) + '</p1>'
+ getAdd1(manager, i) + getAdd2(manager, i) + getAdd3(manager, i)
+ getCity(manager, i) + getPcode(manager, i)
+ '<br>' + getCountry(manager, i) + '<br>'
My issue is with the call to getCountry
+ '<br>' + getWeb(manager, i) + '<br>'
+ '<br>' + getPhases(manager, i)
+ '<br>' + getPspon(manager, i)
+ '<br>' + getOspon(manager, i) + '<br>'
+ '<br>' + getDesc(manager, i) + '<br>'
+ '<br>' + '</div>' + '<br>');
$('#Results').append(row);
}
})
};
After some research I think the problem was that the getCountry method is so long it carries on with the rest of the code and displays it as undefined.
I then came across Promises and tried to add this to the function but now the html page just shows [object Promise].
The getCountry function is shown below and was the same before the addition of the Promise code.
This is what I am trying to achieve
Checks that there is an address and then checks for a country code. Assigns the 3 digit numerical country code to country. Then loads a JSON containing ISO 3166 data process this into a searchable object. Searches the objects for a match to the value stored in country. Then assigns the name field from the matched object to result and then returns it to be displayed at the end of the address.
function getCountry(manager, i){
return new Promise(function(resolve, reject) {
if(manager.data[i].attributes.addresses[0] != null && manager.data[i].attributes.addresses[0].country != null){
var country = manager.data[i].attributes.addresses[0].country;
var c = country.toString();
let url = 'http://data.okfn.org/data/core/country-codes/r/country-codes.json';
fetch(url)
.then(res => res.json())
.then((data) => {
console.log(data);
console.log(manager);
for(var i=0, length=data.length; i<length; i++){
if(data[i].M49 === c){
var result = data[i].name;
console.log(result);
Promise.resolve(result);
}
}
})
}
else {
var reason = " ";
Promise.reject(reason);
}
}
);
}
Where am I going wrong?
Updated code using #Zohaib Ijaz suggestion
fetch(url)
.then(res => res.json())
.then((manager) => {
/* console.log(manager); */
for (i in manager.data){
/* use a Promise in order to receive the result for the below function */
getCountry(manager, i).then((cm)=> {
var row = $('<div id="Data">' + '<br>' + getLogo(manager, i) + '<br>'
+ '<br>' + '<p1>' + getName(manager, i) + '</p1>'
+ getAdd1(manager, i) + getAdd2(manager, i) + getAdd3(manager, i)
+ getCity(manager, i) + getPcode(manager, i)
+ '<br>' + cm + '<br>'
+ '<br>' + getWeb(manager, i) + '<br>'
+ '<br>' + getPhases(manager, i)
+ '<br>' + getPspon(manager, i)
+ '<br>' + getOspon(manager, i) + '<br>'
+ '<br>' + getDesc(manager, i) + '<br>'
+ '<br>' + '</div>' + '<br>');
$('#Results').append(row);
});
}
});
}
The getCountry function
function getCountry(manager, i){
return new Promise(function(resolve, reject) {
if(manager.data[i].attributes.addresses[0] != null && manager.data[i].attributes.addresses[0].country != null){
var country = manager.data[i].attributes.addresses[0].country;
var c = country.toString();
let url = 'http://data.okfn.org/data/core/country-codes/r/country-codes.json';
fetch(url)
.then(res => res.json())
.then((data) => {
for(var i=0, length=data.length; i<length; i++){
if(data[i].M49 === c){
var result = data[i].name;
/* console.log(result); */
resolve(result);
}
else {
var reason = "";
reject(reason);
}
}
})
}
else {
var reason = "";
reject(reason);
}
}
);
}
This is what I see in the Chrome console (24 times)
Uncaught (in promise) test.html:1
What I noticed is that you're calling Promise.resolve(result); when you instantiated the Promise at the start of the function, you passed it a function with two arguments, resolve and reject. Those are what you should be using to 'end' your Promise, so changing them to just resolve(result) and reject(reason) should let your Promise resolve properly.
That said, the point of a Promise is to say "do this, and when that's done, .then do this other thing". So you'd need something like
getCountry(manager, i).then(function(result) {
// result is whatever you passed into resolve() in getCountry
// everything in here is done after getCountry finishes running
// and returns a value
}, function(rejection) {
// rejection is whatever you passed into reject() in getCountry
// this only happens if things didn't work
}
I'm not sure that Promises would work since you're calling the function in the middle of a concatenation. If your other functions make asyncronous calls, an alternative you might consider is to rewrite all of your asynchronous functions as Promises, then use Promise.all() to wait for all of them to resolve before proceeding to concatenate them into HTML. Something like this
var p1 = getLogo(manager, i);
var p2 = getName(manager, i);
var p3 = getAdd1(manager, i);
...
Promise.all([p1, p2, p3]).then(function(results) {
results.join('<br>')
// Whatever else you want to happen once all the functions are finished.
})
getCountry is not a synchronous function call. You need to wait for response.
fetch(url)
.then(res => res.json())
.then((manager) => {
/* console.log(manager); */
for (i in manager.data){
getCountry(manager, i).then((cm)=> {
// Add other values as well.
var row = $('<br>' + cm + '<br>');
$('#Results').append(row);
});
}
});

problems with storing getjson request in variable

I'm having troubles with getting a variable from a getJSON() request. I have the following three functions:
function getPcLatitude() { // onchange
var funcid = "get_postcode_latitude";
var postcode = parseInt($('#input-field-postcode').val());
var jqxhr = $.getJSON('functions/getdata.php', {
"funcid":funcid,
"postcode":postcode}).done(function(dataLatitude) {
if (dataLatitude == null) {
//..
} else {
var myLatitude = 0;
for (var i=0;i<dataLatitude.length;i++){
myLatitude = dataLatitude[i].pc_latitude;
}
return parseFloat(myLatitude);
//alert(myLatitude);
}
});
}
function getPcLongitude() { // onchange
var funcid = "get_postcode_longitude";
var postcode = parseInt($('#input-field-postcode').val());
var jqxhr = $.getJSON('functions/getdata.php', {
"funcid":funcid,
"postcode":postcode}).done(function(dataLongitude) {
if (dataLongitude == null) {
//..
} else {
var myLongitude = 0;
for (var i=0;i<dataLongitude.length;i++){
myLongitude = dataLongitude[i].pc_longitude;
}
return parseFloat(myLongitude);
//alert(myLongitude);
}
});
}
function getTop5Postcode() { // onchange
setTimeout(function() {
var funcid = "get_top_5_postcode";
var er = rangeM3Slider.noUiSlider.get();
var zv = $("#selectzv").val();
if (zv < 1) {
var zv = $("#selectzvfc").val();
}
var zp = $("#selectzp").val();
if (zp < 1) {
var zp = $("#selectzpfc").val();
}
var latitude = getPcLatitude();
var longitude = getPcLongitude();
var chosendistance = parseInt($('#input-field-afstand').val());
var jqxhr = $.getJSON('functions/getdata.php', {
"funcid":funcid,
"er":er,
"zp":zp,
"zv":zv,
"latitude":latitude,
"longitude":longitude,
"chosendistance":chosendistance}).done(function(dataPrices) {
if (dataPrices == null) {
$('#myModalAlert').modal('show');
} else {
//$('#myModalData').modal('show');
var table = '';
var iconClassZkn = '';
var iconClassIp = '';
for (var i=0;i<dataPrices.length;i++){
if (dataPrices[i].zkn_score == 0) {
iconClassZkn = 'no-score';
} else {
iconClassZkn = 'zkn-score';
}
if (dataPrices[i].ip_score == 0) {
iconClassIp = 'no-score';
} else {
iconClassIp = 'ip-score';
}
table += '<tr>'
+ '<td width="75" class="zkh-image" align="center">'+ dataPrices[i].zvln_icon +'</td>'
+ '<td width="250" align="left"><b>'+ dataPrices[i].zvln +'</b><br><i>Locatie: ' + dataPrices[i].zvln_city + '</i></td>'
+ '<td class=text-center> € '+ dataPrices[i].tarif +'</td>'
+ '<td class=text-center> € '+ dataPrices[i].risico +'</td>'
+ '<td class=text-center><a target="_blank" href="' + dataPrices[i].zkn_url + '"><span class="' + iconClassZkn + '"><font size="2"><b>' + dataPrices[i].zkn_score + '</b></font></span></a></td>'
+ '<td class=text-center><a target="_blank" href="' + dataPrices[i].ip_url + '"><span class="' + iconClassIp + '"><font size="2"><b>' + dataPrices[i].ip_score + '</b></font></span></a></td>'
+ '</tr>';
}
$('#top5').html(table);
//$('#myModalData').modal('hide');
}
})
.fail(function() { $('#myModalAlert').modal('show');}); //When getJSON request fails
}, 0);
}
Form some reason the
var latitude = getPcLatitude();
var longitude = getPcLongitude();
parts don't work / don't get a value form the functions. When I change the return in both functions into an alert() it does give me the expected values, so those two functions work.
When I set the two variables directly, like so:
var latitude = 5215;
var longitude = 538;
then the getTop5Postcode() function does work and fills the table.
Any help on this?
Regards, Bart
Do not forget that JavaScript is asynchronous, so by the time you reach the return statement, the request is probably not done yet. You can use a promise, something like:
$.getJSON(....).then(function(value){//do what you want to do here})
Both your functions (getPcLatitude and getPcLongitude) are returning nothing because the return statement is inside a callback from an asynchronous request, and that's why an alert show the correct value.
I would suggest you to change both methods signature adding a callback parameter.
function getPcLatitude(callback) {
...
}
function getPcLongitude(callback) {
...
}
And instead of returning you should pass the value to the callback:
callback(parseFloat(myLatitude));
callback(parseFloat(myLongitude));
And your last function would be somehting like that:
function getTop5Postcode() { // onchange
setTimeout(function() {
var latitude;
var longitude;
getPcLatitude(function(lat) {
latitude = lat;
getTop5(); // Here you call the next function because you can't be sure what response will come first.
});
getPcLongitude(function(longi) {
longitude = longi;
getTop5();
});
function getTop5() {
if (!latitude || !longitude) {
return; // This function won't continue if some of the values are undefined, null, false, empty or 0. You may want to change that.
}
var funcid = "get_top_5_postcode";
var er = rangeM3Slider.noUiSlider.get();
var zv = $("#selectzv").val();
if (zv < 1) {
var zv = $("#selectzvfc").val();
}
var zp = $("#selectzp").val();
if (zp < 1) {
var zp = $("#selectzpfc").val();
}
var chosendistance = parseInt($('#input-field-afstand').val());
var jqxhr = $.getJSON('functions/getdata.php', {
"funcid":funcid,
"er":er,
"zp":zp,
"zv":zv,
"latitude":latitude,
"longitude":longitude,
"chosendistance":chosendistance}).done(function(dataPrices) {
if (dataPrices == null) {
$('#myModalAlert').modal('show');
} else {
//$('#myModalData').modal('show');
var table = '';
var iconClassZkn = '';
var iconClassIp = '';
for (var i=0;i<dataPrices.length;i++){
if (dataPrices[i].zkn_score == 0) {
iconClassZkn = 'no-score';
} else {
iconClassZkn = 'zkn-score';
}
if (dataPrices[i].ip_score == 0) {
iconClassIp = 'no-score';
} else {
iconClassIp = 'ip-score';
}
table += '<tr>'
+ '<td width="75" class="zkh-image" align="center">'+ dataPrices[i].zvln_icon +'</td>'
+ '<td width="250" align="left"><b>'+ dataPrices[i].zvln +'</b><br><i>Locatie: ' + dataPrices[i].zvln_city + '</i></td>'
+ '<td class=text-center> € '+ dataPrices[i].tarif +'</td>'
+ '<td class=text-center> € '+ dataPrices[i].risico +'</td>'
+ '<td class=text-center><a target="_blank" href="' + dataPrices[i].zkn_url + '"><span class="' + iconClassZkn + '"><font size="2"><b>' + dataPrices[i].zkn_score + '</b></font></span></a></td>'
+ '<td class=text-center><a target="_blank" href="' + dataPrices[i].ip_url + '"><span class="' + iconClassIp + '"><font size="2"><b>' + dataPrices[i].ip_score + '</b></font></span></a></td>'
+ '</tr>';
}
$('#top5').html(table);
//$('#myModalData').modal('hide');
}
})
.fail(function() { $('#myModalAlert').modal('show');}); //When getJSON request fails
}
}, 0);
}
Of course, this is far away from the perfect solution for your problem but it should work!
And I did not test this code.
I solved this by doing some extra stuff in mysql queries. Now I only have to use the main function.
Things work now! Thanks for all the help!

Categories

Resources