I need to list items upon search.
Instead of using some kind of loading sign, infinite progress or whatever while the serverside php script finishes it job, I would like to have the results appear as soon as they have been found serverside.
PHP side seams quite easy to perform just a fake 10x result (server.php):
header( 'Content-type: text/html; charset=utf-8' );
$i = 0;
while($i < 10)
{
?>
$('#resultZone-13').append('<div class="fileline">someresult</div>');
<?
flush();ob_flush();
usleep(200000); //0,2s
$i++;
}
clientside, I would have hoped the getScript would work, but it didn't, this is what I have:
$.post('server.php',{}, function(data)
{
},"script");
but this combination waits for the serverside script to fully complete before executing the 10 jquery commands. How can I make JQuery execute the commands as soon as they are received?
The only idea I have would be to load an offscreen iframe and ask to load the server.php page inside this iframe, but then, I'm stuck inside this iframe...
You can't, you will either have to implement socket.io or use $.getScript instead.
Try this :
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'test.php';
$('head').append(s);
Ok, I got this to work after several days off.. (Im a new dad!)
Basically this is the way to do it:
Create an invisible iframe on the document and load the remote php file in it. This php file can flush some javascript content to this iframe, this is the only way i've found to let it display it sequentially.
For instance, I got this test running:
<?
header( 'Content-type: text/html; charset=utf-8' );
echo '<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>';
$i = 0;
while($i < 10)
{
?>
<script type="text/javascript">
$(window.parent.document).find('#subfolder13').append('<div class="folderline"><div class="closedfolder" style="margin-left:48px;"></div>Pecq</div>')
</script>
<?
flush();ob_flush();
usleep(200000); //0,2s
$i++;
}
?>
I don't care about the heavy query load at the begining as this is the exact same file as the caller frame, so in 99% cases this file is freshly cached. If really needed this could be plain javascript, doesn't changes the idea behind this.
Related
Searched a fair bit but couldn't find much about this..
I have a page that is processing quite a few things through a loop, and I have put this at the top of the php page:
ob_implicit_flush(true);
ob_end_flush();
This is happily pumping out the loop to my browser window, but the content is scrolling off the bottom of the page, and I have to keep scrolling down manually. So my question is: How do I get the page or browser window to scroll with the content?
I read somewhere using javascript setInterval to start and end scrolling might do the trick, and it sounds like that might be the case - just make the page start scrolling at the beginning of the script and end when it ends.. but I'm not great with javascript yet so was hoping someone could tell me how to do it?
Another solution I can think of is to somehow get javascript to force focus on a particular element class or something as it is being generated.. but this seems like a potentially clunkier option..
Any quick tips would be great.
Thanks!
There is no need to add thousands of lines of code, just a short function at the top of your output and a line at the end. This works (add the html at the beginning and /html at the end tags to make it pretty; no need though):
<script>
var scroller = setInterval(function() {
window.scrollTo(0,document.body.scrollHeight);
}, 10); // update every 10 ms, change at will
</script>
<?php
// generate 1000 lines of html code
for($i=0; $i<1000; $i++){
echo $i . "<br>";
ob_flush(); // flush out the output as we go
flush(); // same
usleep(10000); // add some delay to see it in action
}
?>
<script>
clearInterval(scroller); // stop updating so that you can scroll up
</script>
Use this javascript:
function getDocHeight() {
var D = document;
return Math.max(
Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
Math.max(D.body.clientHeight, D.documentElement.clientHeight)
);
}
document.documentElement.scrollTop = getDocHeight();
you can simply add the line
document.documentElement.scrollTop = getDocHeight();
to every piece you send to the client in order to update the scrollbar...
or
add this line of code to the beginning of your output:
var scroller = setInterval(function() {
document.documentElement.scrollTop = getDocHeight();
}, 100 /*update intervall in ms*/);
and this line to the end of your output:
clearInterval(scroller);
I'm trying to display the results while PHP script is running, as example.. a really long loop, i want it to echo the results while the page is loading, I searched really a lot through this and i couldn't find the good answer, After googling i found people saying use ob_flush from this question .. but it didn't work, as well as enabling the implicit_flush from php.ini , still didn't work
it only loads when the process is finished, i tried to run a for loop like this
ob_start();
for($i=0; $i<500; $i++){
echo "hm\n";
ob_flush();
}
ob_end_flush();
and still, didn't work.. it shows them all at once
My last guess now is that it needs more PHP configurations to enable/disable some stuff,
or.. it could also be apache2 configurations ?
What are the config settings that are related to this ? settings that needs to be disabled/enabled through Apache or PHP configurations ..
P.S. : I'm sure its possible to be done using PHP alone, I saw it done on GoDaddy hosting and saw it on several websites, of them http://www.checker.freeproxy.ru/checker/index.php .. if you try to submit it will show the results normally without using ajax, the website uses PHP and Apache, there's a mystery secret behind this
I used this way from this answer
while(1) {
echo "should display these lines on browser while in infinite loop.<br>";
flush();
}
or using the for loop, they both work fine, and it to make it more accurate i use ob_flush() with flush()
for($i=0; $i<5000; $i++) {
echo "should display these lines on browser while in infinite loop.<br>";
usleep(30000);
ob_flush();
flush();
}
they both work fine without ajax
Check my post here: Show progress bar in php while loop
It has some sample code as well, and covers pretty much everything you need.
PS: It can't be done with PHP alone, you need to do this with AJAX + PHP (client + server side coding). This is because the response is sent to the browser only after the file is fully interpreted.
You can't do this with PHP. PHP is run server side so it executes before the HTTP response is sent back to the browser.
You would need to use AJAX to achieve this.
You may also look at websockets to achieve this kind of thing.
You could also cheat and load all the data into a hidden list, and then use javascript to show the list items one by one after the page has loaded. :)
As mentioned above, Ajax would be the best method.
You'll need 3 files, a html file or php file that heads the job, a javascript file with your ajax in it and the php file running your script, here's an example of how you could do this. The rest is up to you if you need it tweaking for whatever you are trying to do, but it should give a sequential redout if you break up your php accordingly.
go.hml:
<html>
<head>
<title>Insert Title Here</title>
<script src="ajax_example.js" language="javascript"></script>
</head>
<body>
<form action="javascript:insert()" method="post">
<input type="text" name="limit" value="" id="limit"/>
<input type="submit" name="Submit" value="Go"/>
</form>
<div id="text_response"></div>
</body>
</html>
ajax_example.js:
// make script work for internet explorer too
function createObject(){
var request_type;
var browser = navigator.appName;
if(browser == 'Microsoft Internet Explorer'){
request_type = new ActiveXObject('Microsoft.XMLHTTP');
}else{
request_type = new XMLHttpRequest();
}
return request_type;
}
var http = createObject();
var response = '';
var current = 0;
var limit = 0;
function insert(){
current = 0;
// write to the document
response = 'Hang on...';
document.getElementById('text_response').innerHTML = response;
// set the limit and run the loop script
limit = encodeURI(document.getElementById('limit').value);
limit++;
loop_file(current);
}
function loop_file(i) {
// open the php file you wish to run, the 'hm' and 'rand' are optional, obviously
http.open('get', 'file.php?hm='+i+'&rand='+Math.random());
// run the insertReply function
http.onreadystatechange = insertReply;
http.send(null);
}
function insertReply(){
if(http.readyState == 4){
response = response+'<br />'+http.responseText;
document.getElementById('text_response').innerHTML = response;
current++;
// this runs like a pseudo for loop and will loop until it reaches the 'limit'
if(current < limit){
loop_file(current);
}else if(current == limit){
//create end script here
}
}
}
file.php
<?php
echo isset($_GET['hm']) ? $_GET['hm'] . " - hm\n" : "hm\n";
?>
I would like to know if it's possible without javascript to update an echo ?
For example
<?php
for ($i = 1; $i < 100; $i++){
echo $i;
}
?>
But it will only update the number without adding another line, and another until 100. Is this possible or only with javascript you can achieve this.
I need to output a counter to know how much files is being processed at the moment like
45 of 100 pages
No. client side (JavaScript for example) only. Because if you want to achieve this without page reload, then how PHP could be involved if PHP starts when request from browser comes?
PHP is a server-side language. The script is requested, executed and then sent to the client.
JavaScript executes client-side only. Which means that it can send a request to a PHP script, but will always return the result of the script.
The only option is AJAX requests. Basically, you write a PHP script that moves one file at a time. JavaScript handles the loop from 1 to 100 and send 100 synchronous requests to the PHP script with different parameters. Then you can track the progress and update DOM elements on your HTML page.
jQuery has a nice .ajax() function that can get you started. Below is a quick example. It won't work right off the bat but you can build on it to make it work.
PHP
<?php
$file = $_POST['file'];
$destination = $_POST['destination'];
// Move the stuff!
?>
JavaScript
var files = ['test.txt', 'test2.txt' /* ... */], /* Your list of files... */
destination = '/path/to/send/to/the/php/script/';
for(var i = 0; i < files.length; i ++){
$.ajax({
async: false,
url: 'script_to_move_files.php',
data: { file: files[i], destination: destination },
success: function(){
/* File moved! Update a progress bar or something... */
},
error: function(){
/* File wasn't moved successfully... */
}
});
}
I need to force my PHP page to display the message after each round in a loop .. not at the end of loop .. as i'm running an infinite loop.
the goal is that i have a script inside a page that runs a command on the server .. takes the output and compares the data with in IF statement if it checks it displays a message .. if not .. it sleeps for three seconds and runs the loop again.
the problem is when i run the php file from a command line on the server it does exactly what it should do .. displays a message every 3 seconds (not pressing the confirmation button).. but when i run it in a browser it displays nothing (it waits for the loop to end!)
not sure if my below example will serve the purpose though.
<?php
while (1==1) {
$answer = shell_exec ("COMMAND'");
list($src, $app, $cid, $non, $flag, $dur, $exten) = explode("!", $answer);
if ($cid > 0) {
echo "<script language='javascript'>
var r=confirm('You have a call from $cid: Show Data?')
if (r==true)
{
OPEN A WEB PAGE INSIDE AN IFRAME
}
</script>";
//header( 'refresh: 15; url=monit.php' );
flush();
sleep(10);
}
else {
//header( 'refresh: 1; url=monit.php' );
sleep(1);
}
}
?>
Please note that i tried to use "header()" function to reload the page however i don't want to reload the page itself (will create a complication inside the parent page)
Any suggestions?
There are a few things to check mentioned in the manual page for the flush function:
flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser
Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.
Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.
There are also some config file options that need to be checked mentioned in the comments
If flush() function does not work. You must set next options in php.ini like:
output_buffering = Off
;output_handler =
zlib.output_compression = Off
;zlib.output_handler =
I've also notice there are commented out lines to cause the page to refresh - you do not need to refresh the page to see the new output, the browser should show the page as still loading until the script has completed.
As has been said unless you have full control over the server this would be impossible to implement, and even if you did if you wanted to keep the connection open for a considerable length of time it would probably time out, requiring client-side continuation.
Thus, it would probably be a better idea to use AJAX, for example:
ping.php
$answer = shell_exec('COMMAND');
$r = array();
list($r['src'], $r['app'], $r['cid'], $r['non'], $r['flag'], $r['dur'], $r['exten']) = explode("!", $answer);
if($r['cid'] > 0)
$r['success'] = true;
else
$r['success'] = false;
echo json_encode($r);
Script in your public HTML/PHP file
<script type="text/javascript">
// If you're using jQuery...
var ping = function() {
$.ajax('ping.php', {
dataType: 'json',
success: function(data) {
if(data.success && confirm('You have a call from ' + data.cid + ': show data>'))
$('iframe').attr('src', 'new_page.php');
}
});
};
setInterval(ping, 3000);
</script>
Drop this into your htaccess (turns of gzip):
SetEnv no-gzip dont-vary
and to echo the message and flush output buffer do this in your loop:
echo $msg;
ob_flush();
flush();
I was wondering how to make progress bar like gmail.
I tried
<script src="jquery.js"></script>
<script>
$(function (){
$.ajax({
url: 'index.php',
success: function(data) {
$('#bar').html(data);
}
});
})
</script>
<div id="bar"></div>
And on index.php
[EDIT]: by sleep() i just meant to simulate continuous stream of output like multithreaded programs which is not supported in php.
<?php
for($i=0; $i<=10; $i++)
{
sleep(1);
echo "$i";
}
it seems that output is echoed out at once so i get result 012345678910 at once.
also i tried
setInterval(function (){
$.ajax({
url: 'index.php',
success: function(data) {
$('#bar').html(data);
}
});
}, 1000);
Instead, i had trouble maintaining value of 'progress', so i did
<?php
session_start();
if(isset($_SESSION['value'])){
if($_SESSION['value'] >= 10)
{
unset($_SESSION['value']);
}
else
{
$_SESSION['value']++;
}
}
else
{
$_SESSION['value'] = 0;
}
echo $_SESSION['value'];
as part of my php. But it seems that, i am calling ajax function on continuous interval.
My Question is,
How does google use progress bar, while loginng in gmail. Do they get continuos 'stream' of data like i tried on my first example or send (regularly) request on some url (though not through ajax .. through JSONP or whatever) and upadate the page like second ?
Can I do same with php , even if not with php, can I do it using javascript and other server side scripting language where multithreading is supported?
I'm not sure what exactly Gmail does for the progressbar, but you can achieve something similar in PHP, although it may be a bit tricky.
First, to explain why your examples don't work:
If you echo and sleep, like your first example, it will never work. Ajax performs a full request - that is, if the response does not finish, it will wait. When you loop and sleep, the request is not "closed" until the PHP script has finished executing.
If you use session, like in the other example, the problem becomes the session store. The store is typically locked during script execution, and it will not update itself to allow for the type of progress check you want.
What you could do is write progress to a file (or to a database) manually. For example:
file_put_contents('progress.txt', 1);
Then, have another script read the file and output the contents.
This should work, because file_put_contents opens, writes and closes the file.
Using some other language than PHP would make it easier. Being multithreaded would possibly make it easier, but is not a requirement. However, having a continuously running process would make it simpler (PHP only runs a process for the duration of your request and then exits)
run your jquery code at an interval, and use PHP to print the progress percenage and draw the bar then.
so it will be something like
<script>
function bar()
{
var v=getProgress(...);
setTimeout("bar()",1000);
drawBar();
}
function drawBar(l)
{
//set div's length to l
}
</script>
EDIT 2
<?php
/* get the request and calculate the job completion percentage and echo it ! */
?>
I think Gmail shows progress when it loads all resources, like JS files. There are different ways to do this: you could dynamically include all resources with JS, or you could make all included JS files report that they've been loaded.
To make PHP output partial output, use this:
ob.php
<?php
ob_start();
for ($i = 0; $i < 100; $i++) {
echo "{$i}<br />";
ob_flush();
flush();
usleep(100000);
}
.htaccess
php_value output_buffering "0"
this thread and this link helped me to find out solution for the same problem, so i am providing it for the record:
test.php:
<?php
for($i=0; $i<100; $i++)
{ usleep(100000); //100ms
echo 'A'; ob_flush(); flush();
}
?>
test.html:
<body>
<button onclick='call()'>call</button>
<div id='progress'>...</div>
<script>
function fprogress(e)
{ document.getElementById('progress').innerHTML ='progress: '+e.loaded +'%'; }
function call()
{ var req = new XMLHttpRequest();
req.addEventListener("progress", fprogress, false);
req.open('GET', 'test.php', true); req.send(null);
}
</script>
</body>
... so test.php can be any JOB which doing some stuff... and while doing it ECHOes 100 characters (bytes) with flashing buffer.
As per my opinion, you can divide your login process in several parts and checks.
Every part check completed send response to your progress bar and progress bar width will increase such patterns. After that progress bar will send next request to your login process for step untill you will not get upto 100% login and redirect.