STEP 1. Background
I currently have a working query system for dynamically updating orders from a backend system. When updates are requested, a table is created, which is then updated as the status of an order is received.
1. I query how many orders are open from MySQL and then create a table based on this info. The key ingredient is a div which has the info on the orders that need to be updated (updateref)
2. When the page is loaded, a script is used to call a page that does the actual order query and possible update.
Order list snippet:
Usage: fetch orders that need to be updated to a table, using PHP and MySQL. There can be from 0 to many updates, typically ca. 15-30 updates/rows/div elements.
while($row = $results->fetch_assoc()) {
print '<tr><td>'.$row['reference'].'</td><td><div id="updateref'.$row['reference'].'"><h6>Update queued</h6></div></td></tr>';
}
Script for updating the list:
Usage: fetches the updated status (using orders_updatestatus.php with the div reference created above) for each div.
<script type="text/javascript">
// Update status for each order
$("[id^=updateref]").each(function(index, element) {
$.ajax({
'url': "orders_updatestatus.php?reference=" + element.id.replace(/\D/g, ""),
'success': function(data) {
element.innerHTML = data;
}
});
});
</script>
Please note that everything up to this point is working great!
STEP 2. What is needed
I need to create a progress bar that would dynamically update when each of the divs are completed (when they have been replaced by orders_updatestatus.php using the script mentioned above)
Progress bar script:
I use a standard Bootstrap progress bar, which is static.
<div class="progress">
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 10%"></div>
</div>
The above script displays exactly the kind of progress bar that I need, however I need to make it dynamic, as in update the width: xx% when each div element has been updated.
What I'm thinking is that I need a counter for every div element, add those up and then calculate a percentage based on that that would be then fed as the new width to the progress bar.
Also, it seems that a number of people have asked a similar questions related to progress bars, but the other questions didn't have hardly any answers. Therefore any help on this would be greatly appreciated, thank you.
UPDATE - Nearly working!
Wow, thank you so much for the help @Roamer-1888 , I nearly got the dynamic progress bar working!
// Then aggregate `promises` using $.when()
$.when.apply($, promises)
// .then's callback will fire when all the promises have successfully settled.
.then(function() {
// Set up truthy (completed query)
var spans = $( "span" );
var completed = elements.reduce(function(runningTotal, div) {
if($("h6").find(spans).css( "color", "yellow" )) { // some jQuery expression that returns truthy for "completed", otherwise falsy.
return runningTotal + 1;
} else {
return runningTotal;
}
}, 0);
var n = $("[id^=updateref]").length; // total number of "order" divs
$progressBar.css({width: (100 * completed / n)+"%"}, 100);
});
As you can see from the code above, I used span and h6 tags as the 'thruthys'.
What is working:
- The progress bar goes from 0-100% (the calculations are working)
Problem / what is not working:
- The updates happen only after every query (~30) have been completed. I added a .css( "color", "yellow" ) as a debug to the code and it confirms that the text color inside the completed queries (h6 tags) change to yellow only after ALL of them have been loaded.
So all in all the only thing I still need is to get updates happening as soon as one of the queries is completed and not the updates (changing of text color to yellow and progress bar update) only happens once. Is there a glitch in the .when.apply perhaps?
UPDATE - one glitch still remains
I added an id tag to the progress-bar and went to check whether the completed -number updates correctly as that is the key ingredient for the progress bar itself.
document.getElementById("progressbar").innerHTML = n + " / " +completed;
The problem is that as soon as the first one of the 29 test orders get updates, the completed -number goes to 29 / 29 and the progress bar jumps to 100%, but it takes a number of seconds for all of the 29 lines to update. This is very peculiar, since there is no way that the if($("h6").find(spans) -code can find any h6 or span tags, since they are created seconds later.
What on earth is going on? :-/
THIRD UPDATE
Well, just like before everything is nearly working with the exception of the glitch described above.
Here's my current code:
// First, create an array from the jQuery collection returned by $("[id^=updateref]").
var $progressBar = $('.progress-bar');
var elements = $("[id^=updateref]").get();
var n = elements.length;
// Set up truthy (completed query)
var spans = $( "span" );
// Then map `elements` to an array of jQuery promises; each promise deriving an $.ajax() request.
var promises = elements.map(function(element) {
return $.ajax({
'url': "orders_updatestatus.php?reference=" + element.id.replace(/\D/g, ""),
'success': function(data) {
element.innerHTML = data;
// here use `Array.prototype.reduce()` to scan the elements and summate those that are "completed"
var completed = elements.reduce(function(runningTotal, div) {
if ($("span").find("h6").css({"color": "red", "border": "2px solid red"})) { // some jQuery expression that returns truthy for "completed", otherwise falsy.
return runningTotal + 1;
} else {
return runningTotal;
}
}, 0);
document.getElementById("progressbar").innerHTML = n + " / " +completed;
$progressBar.css({width: (100 * (completed / n))+"%"});
}
});
});
The code now updates all the 29 order cells at the correct time (border to red), and if I remove the +1 from the runningTotal inside the progress bar, the progress bar does not move.
Therefore I have concluded that the if -statement that calculates the runningTotal is working. However, the completed count goes up before the updates are even created.
And to make sure this isn't a cache issue, I added the following caching parameters to the header, just in case. No luck though.
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
@Roamer-1888 , if you or anyone else could spare any more help on this matter, I'd greatly appreciate it. Thank you.
` tag?
– Roamer-1888 Dec 17 '17 at 01:16` or are they siblings?
– Roamer-1888 Dec 17 '17 at 02:27