Until now, you have been opening a shell or terminal to execute your script, but now your boss wants to be able to execute the script, but he doesn’t know anything about CLI(command line interface) commands. So, what can you do? how about having a web interface that allows him to easily activate the script. Yes, that would work and its easy too. But if the script takes 5 min to complete, we don’t want to show a blank page during those 5 mins. It would be better if there was a progress bar that showed how much percentage of the script is completed. Today, we will learn to do just that, Create a progress bar to display server’s php script execution using JQuery and JQueryUI.
In this tutorial, we will create a
1. For server side, php script that needs to be run. For the sake of simplicity we will create a script that need to count 1 to user input number.
2. For the client side or for your boss in this case, create a webpage with a form. The form will take a number till which we want the server to count. When submitted it will trigger the script in the server.
3. While the server is counter, we will update the total and the current count in the json file. We will use php function json_encode.
4. The client end javascript with jquery/jqueryui will collect the values from the json file and update the progress bar every few seconds.
Read the comments for more details.
serverscript/server.php
'0', 'current'=>'0'); fwrite($fp, json_encode($arr)); fclose($fp); //update the total $arr['total'] = $num; //start our simple main logic, ie...start counting. we will start counting from 1 till the num+1. since I am using $i<$num, thats why i add +1 here. for($i = 1; $i < $num+1; $i++){ //here you can do some other work as well. $arr['current'] = "$i"; $fp = fopen($filename, "w"); fwrite($fp, utf8_encode(json_encode($arr))); fclose($fp); //for safety we will make a copy and let client access the copy. copy('status1.json', 'status.json'); } ?>
index.html
<html> <head> </head> <body>
count please
</body> </html>
js/myscript.js
this file contain our function to handle the client side. It uses the jquery library. We put all our code in $(‘#submit-button’).click’s callback function. That is because we want things like updating the progress bar, requesting data from server etc to happen only after user submit the form.
/* when the submit button is clicked we will hide the message div. get the input provided by user and start processing. */ $(document).ready(function(){ $("#submit-button").click(function(){ /*hide the message div box. since we don't have anything to show at this time.*/ $('#message').hide(); /*grab the input by user and save in variable userinput*/ userinput = $("#num").val(); /*prepare a query string. We need to pass the userinput to the script. we grabbed the input from user, now we need to pass it to the */ var dataString = "num=" + $("input#num").val(); /* using ajax we will call the server.php script. dataString is the parameter we got from user.datatype is the data type we expect as return. when complete, set the progress bar to 100% and display the message 'complete'. */ $.ajax( { url : "serverscript/server.php", type: "GET", data: dataString, datatype:"json", complete:function(){ $("#progressbar").progressbar({ value:100}); $('#message').html('Complete'); $('#message').show(); } } ); /* call the updateStatus() function every 3 second to update progress bar value. */ t = setTimeout("updateStatus()", 3000); }); }); /* .getJSON will get the json string being updated by the server.php in server. every 3 second, the 'total' and 'current' count will be parsed and updated to the progress bar. */ function updateStatus(){ $.getJSON('serverscript/status.json', function(data){ var items = []; pbvalue = 0; if(data){ var total = data['total']; var current = data['current']; var pbvalue = Math.floor((current / total) * 100); if(pbvalue>0){ $("#progressbar").progressbar({ value:pbvalue }); } } if(pbvalue < 100){ t = setTimeout("updateStatus()", 3000); } }); }
This is a sweet post! I have been wanting to setup a secure admin console to be able to control the services running on our web servers from a web page.. vs having to connect to the server and restart services, etc. So with this it looks like I can setup a complete set of server management scripts and execute them from a webpage and get some progress so I am not just blindly hoping that services are stopping and restarting… very cool.
Hi, thanks for the post. I tried the codes above, but the progress bar only shows when the count is completed to 100%. Is there any suggestions I can try out? Thanks!
@Leo try moving the $(document).ready(function(){…} script to the bottom of the html file just before tag rather than in the
.also you can check the json file and see if it is getting overridden every 3 sec with new value.
if you put far less number to count lets say 100, the process may complete before 3 sec and become 100% suddenly. change the 3000 ms to much less.
Hi thanks for the reply. I tried your suggestion (moving the function to the bottom of the html page) but still the same thing. I checked the json file and it is updating and getting overridden every 3 secs with new value. Also I am setting the numbers to be 10000 or more. I tried it in IE9, Chrome and Firefox. Any more help will be very appreciated. Thank you.
Great tutorial here. May I use this in one of my open source projects?
Yes sure you can use. Hope it helps to your project.
Also, I think you have a syntax issue in your php on line 8:
$arr = array(‘total’=–>’0′, ‘current’=>’0′);
Sounds like a cool bit of code, I do have a couple of questions though.
1.) Could the progress bar be updated using CSS? (i.e. changing the width of the “progress” from 0% to 100%) so it would start off 0% width, and increase to 100% (with a background color, say green)?
2.) What happens if the PHP ini time is very short (say 30 seconds) or the script that’s running is very long (say 1hr) – how can this be handled in the above?
Cheers
Mike
Would you be able to make the jquery/jquery-ui.css available?
Many Thanks
Hi,
How would you adapt this to make the progress bar work for more than 1 client at a time. I think the way you have it, if a second client comes in while the first one is in the middle of the operation, the progress file will get stomped on by the two executing scripts and the progress returned may not always be correct for each client since they’re sharing the same progress file (status.json).
An idea I had would be to split this up into 2 client-side requests. The first request would return some kind of token to uniquely identify the client’s result file. Then the 2nd request can pass this token back to the server along with the “num” so that the server-side script knows which file to update for this client.
Is there a better way to do this?
You are right. My example will only work for a single client. and that can be solved using a token like you said. thanks.
You can also store the progress in a session, rather than in a file.