A progress bar in browser showing progress of long-lasting PHP function
It uses the HTML5 EventSource interface to receive server-sent events (push notifications) from a PHP script running on the web server. Also the CSS styling of a HTML progress bar is shown.
How it looks like:
Press "Start" to watch the progress bar in action.
How it is done:
test.html
:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div>Press "Start" to watch the progress bar in action.</div>
<div class="button_left">
<button onclick="start_task();">Start</button>
</div>
<div>
<progress id="progress1" value="0"></progress>
<div id="status1" style="min-height:20px;"></div>
</div>
</body>
</html>
script.js
:
var source = "";
function start_task() {
// define the EventSource object and the
// push notifications sending server side script
var php_file = "test.php";
source = new EventSource(php_file);
// reset the progress bar to zero
document.getElementById("progress1").value = 0;
// write a status message
document.getElementById("status1").innerHTML(" Please wait ...");
// a message is received
source.addEventListener("message", function(e) {
// data is JSON encoded on the server
var result = JSON.parse(e.data);
// set progress bar and status message according to received value
document.getElementById("progress1").value = result.progress/100;
document.getElementById("status1").innerHTML(result.progress+" %");
if(result.message == "TERMINATE") {
source.close();
document.getElementById("progress1").value = 1;
document.getElementById("status1").innerHTML("100 % - Ready!");
}
}, false);
// an error is received
source.addEventListener("error", function(e) {
document.getElementById("status1").innerHTML("UUps: There was an error!");
source.close();
}, false);
}
test.php
:
<?php
// try to prevent php timeout
ini_set("max_execution_time", "1000");
// make sure apache does not gzip this type, else it would get buffered
header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache');
function sendMsg($id, $message, $progress) {
$d = array("message"=>$message, "progress"=>$progress);
echo "id: $id" . PHP_EOL;
echo "data: " . json_encode($d) . PHP_EOL;
echo PHP_EOL;
// push the data out by all force
ob_flush();
flush();
}
$i=0;
// usleep simulates a long-lasting preparing function (i.e. SELECT JOIN etc.)
usleep(1000000); // wait 1s
// the long lasting function we want to watch the progress
$big_number = 10000;
while ($i < $big_number) {
// usleep simulates a long-lasting function (i.e. INSERT/UPDATE, big calculation etc.)
usleep(200);
sendMsg(++$i, "", $i/$big_number*100);
}
// ready message
sendMsg(++$i, "TERMINATE", 100);
?>
style.css
:
/* Reset the default appearance */
progress {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
/* webkit-browser: z.B. Chrome, Opera (>12) */
progress::-webkit-progress-bar {
background: #EFEFEF;
border-radius: 5px;
}
progress::-webkit-progress-value {
background-color: #C5A000;
border-radius: 5px;
}
/* Firefox */
progress::-moz-progress-bar {
background-color: #C5A000;
}
/* all browsers */
progress {
background: #EFEFEF;
border-radius: 5px;
border: 1px solid #C0C0C0;
width: 300px;
height: 10px;
color: #C5A000 /* only IE10+ needs this */;
}
.button_left {
float: left;
padding-right: 20px;
}