I'm currently stuck on the frontend of a plugin I am writing. I am trying to defer the execution of a filter function for HTML table row elements (hide(), show()) and markers on a leaflet map until after they are created, but Firefox always gives me the error
TypeError: job.tableRow is undefined
If I comment out the tableRow creation I get exactly same Problem with the markers on the leaflet map.
I've been reading a lot about jQuery deferred objects and tried 2 or three ways to implement them, but it seems like I am still missing something important.
What works: I can sucessfully filter the jobs that are shown/hidden in the list and on the map manually after the page was completely loaded.
However, if I try to do some initial filtering I get the error. Seems like the filtering function is executed before tableRow was created.
So my current code looks like this:
//inside the "main" function
if(jobs != null){
/* this code works
createMarkers(jobs);
createJobTable(jobs, tableBody);
*/
//but like this it does not
$.when( createMarkers(jobs), createJobTable(jobs, tableBody)).done(filterJobs);
function filterJobs(){
...
//go through array of jobs and hide markers and list entry of those, with status that is not checked
for (i = 0, max = jobs.length ; i < max; i++){
job = jobs[i];
if (shownJobStatus.includes (job['status']) ){
job.tableRow.show();
job.marker.addTo(jobmap);
}
else {
job.tableRow.hide();
job.marker.remove();
}
}
}
function createMarkers(jobs){
jQuery(function($){
var deferred = $.Deferred();
for (i = 0; i < jobs.length; i++){
//extract lat, lon, ... from job, I leave out again
job.marker = L.marker([lat, lon], {icon: markerIcon}).addTo(jobmap);
job.marker.bindPopup(jobName).openPopup();
}
deferred.resolve();
return deferred;
})
}
function createJobTable(jobs, tableBody){
jQuery(function($){
let promiseArray = [];
for (i = 0; i < jobs.length; i++){
job = jobs[i];
promiseArray.push( createJobTableEntry(job, tableBody) );
}
deferred.resolve();
return Promise.all(promiseArray);
})
}
function createJobTableEntry(job, tableBody){
jQuery (function($){
let defer = $.Deferred();
const jobId = job['id'];
job.tableRow = $("<tr></tr>");
tableBody.append(job.tableRow);
//put lots of stuff in the table like this
job.tableRow.append($("<td></td>").text(job.jobName));
//lots of user-role dependant stuff
defer.resolve();
return defer.promise();
})
}
I thought the line
$.when( createMarkers(jobs), createJobTable(jobs, tableBody)).done(filterJobs);
should execute filterJobs() only after the deferred that createMarkers and createJobTable return are resolved. The deferred should be resolved only after all the elements where created. So why does this not work?