Scenario:
I have two PHP scripts to be called simultaneously:
The first script will run several minutes (PHP based file download), depending on downloaded file size. It is placed into <iframe> so it can run separately and does not block the browser.
The second PHP script is supposed to be called in regular intervals to monitor execution of the first script - file progress download. To avoid opening new windows upon script completion, it is called via AJAX.
Problem:
I have placed the long-running PHP Script (download script) into <iframe> so this script can run asynchronously with other monitoring PHP script. However, despite the main script is in <iframe>, when the webpage starts execution, the script starts and blocks execution of the remaining JavaScript code and monitoring script called multiple times via AJAX.
It is important to have the short-running monitoring PHP script called simultaneously with the long-running PHP (download) script, so the short-running (monitoring)script can provide feedback to JavaScript.
Would you be so kind and analyze my code samples please? I have no idea, where is my problem. My code is so simple, that everything should be running well.
PHP Version 5.4.12
Apache/2.4.4 (Win64) PHP/5.4.12
Windows 7 x64
8GB RAM
Google Chrome Version 30.0.1599.101 m
Code Samples:
JavaScript code calling both PHP scripts:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body onload="callScripts();">
<script type="text/javascript">
// call both PHP scripts(download and monitoring) in desired order
callScripts = function()
{
// call the monitoring PHP script multiple times in 2 second intervals
window.setTimeout(function(){startDownloadMonitoring()}, 1000);
window.setTimeout(function(){startDownloadMonitoring()}, 3000);
window.setTimeout(function(){startDownloadMonitoring()}, 5000);
window.setTimeout(function(){startDownloadMonitoring()}, 7000);
window.setTimeout(function(){startDownloadMonitoring()}, 9000);
};
// call monitoring PHP script via AJAX
function startDownloadMonitoring()
{
console.log("Calling startDownloadMonitoring()...");
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
console.log("Response Received: " + xmlhttp.responseText);
}
}
xmlhttp.open("GET", "PHP/fileDownloadStatus.php", true);
xmlhttp.send();
}
</script>
<iframe src="PHP/fileDownload.php"></iframe>
</body>
</html>
PHP Monitoring Script(fileDownloadStatus.php)
<?php
include 'ChromePhp.php';
// start session, update session variable, close session
session_start();
$_SESSION['DownloadProgress']++;
ChromePhp::log('$_SESSION[\'DownloadProgress\'] = ' . $_SESSION['DownloadProgress']);
session_write_close();
echo "success";
?>
PHP long-running script (fileDownload.php)
<?php
include 'ChromePhp.php';
// disable script expiry
set_time_limit(0);
// start session if session is not already started
session_start();
// prepare session variables
$_SESSION['DownloadProgress'] = 10;
session_write_close();
for( $count = 0; $count < 60; $count++)
{
sleep(1);
print("fileDownload Script was called: ". $count);
echo "Download script: " . $count;
ob_flush();
flush();
}
?>
Screenshot:
PHP Scripts Execution Order - browser waits to finish the script in <iframe>
Your problem is as simple as you can imagine. You just don't realize it maybe for a bit lack of knowledge of HTML. So Your code is ok and everything is working as you want but the script that should run at the same time isn't, what is the problem?
<body onload="callScripts();">
This up here is your problem. The onload call only takes place when everything inside the body tag is completely loaded. So, as your iframe is inside the body the html interpreter load everything (including the iframe and its source), then call your callScripts function.
To solve your problem I recommend you to create your iframe inside your script. Would be something as this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<!-- You should always define your script in the head tag. best pratice
defined in W3C -->
<script type="text/javascript">
callScripts = function (){
//write your Iframe Here
document.getElementById("callDownload").innerHTML = '<iframe src="PHP/fileDownload.php"></iframe>';
callScripts_refresh();
}
// call both PHP scripts(download and monitoring) in desired order
callScripts_refresh = function()
{
// call the monitoring PHP script multiple times in 2 second intervals
window.setTimeout(function(){startDownloadMonitoring()}, 1000);
window.setTimeout(function(){startDownloadMonitoring()}, 3000);
window.setTimeout(function(){startDownloadMonitoring()}, 5000);
window.setTimeout(function(){startDownloadMonitoring()}, 7000);
window.setTimeout(function(){startDownloadMonitoring()}, 9000);
};
// call monitoring PHP script via AJAX
function startDownloadMonitoring()
{
console.log("Calling startDownloadMonitoring()...");
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
console.log("Response Received: " + xmlhttp.responseText);
}
}
xmlhttp.open("GET", "PHP/fileDownloadStatus.php", true);
xmlhttp.send();
}
</script>
</head>
<body onload="callScripts();">
<div id="callDownload"></div>
</body>
</html>
Let me know if it work after that
Related
I have started working my way through the AJAX tutorial on the W3Schools website and my first example won't even run. Why won't this run please? It opens up in the browser but nothing happens when I click the button.
The tutorial URL;
https://www.w3schools.com/js/tryit.asp?filename=tryjs_ajax_ie
Here is my HTML page that I created in Notepad++
<!DOCTYPE html>
<html>
<body>
<h1>The XMLHttpRequest Object</h1>
<p id="demo">Let AJAX change this text.</p>
<button type="button" onClick="loadDoc()">Change Content</button>
<script>
function loadDoc() {
var xhttp;
if (window.XMLHttpRequest) {
// code for modern browsers
xhttp = new XMLHttpRequest();
} else {
// code for IE6 and IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
}
</script>
</body>
</html>
I run the HTML page by selecting Run >> chrome in Notepad++ (but tried Firefox and IE too). The ajax_info.txt file is in the same location as the HTML file. Here is its contents;
AJAX is not a programming language.
AJAX is a technique for accessing web servers from a web page.
AJAX stands for Asyncronous JavaScript And XML.
you must change xhhtp.onreadystatechange instead of xhttp.onreadystatechange and xhhtp.send(); instead of xhttp.send();
function loadDoc() {
debugger;
var xhhtp;
if (window.XMLHttpRequest) {
// code for modern browsers
xhhtp = new XMLHttpRequest();
} else {
// code for IE6 and IE5
xhhtp = new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhhtp.open("GET", "ajax_info.txt", true);
xhhtp.send();
}
Because of the typo xhhtp instead of xhttp.
You should read up on CORS. For example:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Your can see your code working if you run a local web server, which serves the html file in question (keep the txt file in the same directory as the html file).
If you are on a mac, an easy way to run a local web server is to run the following code from where your html file is:
python -m SimpleHTTPServer 8001
then in your browser go to
http://localhost:8001/yourhtmlfile.html
Since you mentioned notepad++, seems you are not on mac, but some light googling will give you a similar setting for windows.
Thanks everyone. I installed Apache and set port to 7777 (because already had IIS on port 80) and placed files in htdocs location of apache and used the url http://localhost:7777/htdocslocation/FirstAJAXExample.html and it worked.
I am using Ajax in my project so in header.php i am using Javascript code for sending the XMLHttpRequest to the server. I am including this header.php file in every page of the website.
Problem is here that in signin.php page i am using header function. That is not working due to the Ajax code i am using in the header. When i remove that code from the header.php. header function working fine.Please help me out.
header function i am using in signin.php:
header("location:index.php");
Ajax Code using in header.php :
<script>
function favourite(str)
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("like-div").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","add_to_favourites.php?"+str,true);
xmlhttp.send();
}
</script>
Actually, the Location header does work, but it redirects the Ajax request that runs in the background instead of triggering a full URL change in the browser. Browsers handle this redirection of the Ajax request transparently, so what ends up happening is that the contents of #like-div are replaced by the full HTML code of index.php.
Obviously this is not the intended behavior in this case, so what we need to do is detect somehow that the redirect has happened during an Ajax request, and send back some JavaScript to manually set document.location in the browser.
A possible solution is using jQuery for placing the Ajax request (as it supports browser-independent execution of scripts in the response), and sending the JavaScript redirect code instead of a Location header when an XMLHttpRequest is detected:
JavaScript
$("#like-div").load("add_to_favourites.php?" + str);
/* see how much easier it is with jQuery? */
header.php
/* Function for Ajax-friendly redirects */
function redirect_with_ajax($url, $permanent = false)
{
#ob_end_clean();
if(isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest")
{
print('<script> location.href = ' . json_encode($url) . '; </script><div>You are being redirected here.</div>');
}
else
{
header($_SERVER["SERVER_PROTOCOL"] . " " .
($permanent ? "301 Moved Permanently" : "302 Found"));
header("Location: " . $url);
}
exit;
}
/* Do the redirect */
redirect_with_ajax("index.php");
The code is untested and may contain errors. Use it with caution.
This question already has answers here:
What is the difference between client-side and server-side programming?
(3 answers)
Closed 9 years ago.
I figured how i can get a dialog and seems like i need to use javascript but this doesnt let me follow up with php code depending on the answer unless there is a way?
<?php
$ime = "Marko";
echo <<< EOT
<SCRIPT language="JavaScript">
var hi= confirm("Do you really want to deactivate $ime?");
if (hi== true){
<?php ?>
alert("$ime Deactivated!");
// I need to do php code here...
}else{
alert("Skipping $ime");
// I need to do php code here...
}
</SCRIPT>
EOT;
?>
Improving on #papirtiger's answer, you could use AJAX to pass onto the PHP code seamlessly without a page reload.
All AJAX really is is the way you can pass data from javascript to a PHP file. Because PHP is server side, any PHP script that needs to be executed MUST be on the server. PHP generates the script and sends it to the client and the connection between the client and the server is done when the generated page downloads. Javascript can continue its work as it is client side. But since it's on the client's machine, it can't run a PHP script inside it as it can't be interpreted.
AJAX takes data from PHP and sends it like a Form would (using POST or GET variables), executes a separate PHP file on the server, grabs the response from the script and puts it into the javascript without the entire page reloading.
Here is what your script could look like.
<script>
if (window.confirm("Are you sure?")){
// Begin the AJAX function
$.ajax({
// Declare the type (GET or POST)
type = "POST",
// The local server location to the PHP script to get the response from
url = "yes.php",
// Data to send (in this case nothing needs to be sent)
data = "",
// Get the response if a script is executed successfully
success: function(response) {
// Display the response from the script in an alert box
alert(response);
}
)};
} else {
// Rinse and repeat using another file
$.ajax({
type = "POST",
url = "no.php",
data = "",
success: function(response) {
alert(response);
}
)};
}
</script>
You would also need to include the jQuery library in the head of your HTML otherwise this AJAX markdown will not work and you would have to result to traditional (and ugly/messy) pure javascript AJAX executions.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Hope this helps! :)
PHP is a server-side scripting language. You can not trigger it with JavaScript.
#StashCat´s answer is totally correct, however the pattern you are looking for is something like this:
<script>
if (window.confirm("Are you sure")){
window.location("/yes.php");
} else {
window.location("/no.php");
}
</script>
Note that the script that is running will continue until it exits.
The user is then presented with the web page and the confirm box. When they click the yes or no they will be redirected and a new script will be run.
in a nutshell, its not a good solution for languages mix like this. According to a code you have, i can declare a global varaibale with php like <?php <script> var some = "123"; </script> ?> and then use it in client javascript code, but i'll repeat its bad approach. You'd better to refactor your code.
Php code runs on Server, while javascript code runs on client i.e., your browser. So, you can't write code to display a dialog box at server side, But you can dynamically remove and add HTML elements using Ajax. You can code your dialog box in javascript and call an Ajax block. A typical example of Ajax(Ajax--> Async Javascript) code,
<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv"><h2>Let AJAX change this text</h2></div>
<button type="button" onclick="loadXMLDoc()">Change Content</button>
</body>
</html>
Scenario:
I have two PHP scripts to be called simultaneously:
First script will run several minutes (PHP based file download), depending on downloaded file size
Second PHP script is supposed to be called within regular intervals to monitor execution of the first script - file progress download. To avoid opening new windows upon script completion, it is called via AJAX.
Problem:
The regularly called AJAX monitoring script is not processed during the execution of the first long running PHP(later download) script. Only if the first script is finished the AJAX called PHP script gets processed.
I spent many hours over this problem. I have simplified my test scripts as much as possible. However, I still can not get the AJAX script working during execution of the main php script. Neither can I obtain intermediary feedback values from the main-download script, in any other way.
Would you be so kind and analyze my code samples please? They have the precise form as I use them now. If possible, would you be so kind and run them in your environment? I suspect the problem can be in my WAMP environment.
PHP Version 5.4.12
Apache/2.4.4 (Win64) PHP/5.4.12
Windows 7 x64
8GB RAM
Code Samples:
JavaScript code calling both PHP scripts:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body onload="callScripts();">
<script type="text/javascript">
// call both PHP scripts(download and monitoring) in desired order
callScripts = function()
{
// run long running (later Download) PHP script
console.log("Calling: PHP/fileDownload.php");
window.location.href = 'PHP/fileDownload.php';
// call the monitoring PHP script multiple times in 2 second intervals
window.setTimeout(function(){startDownloadMonitoring()}, 1000);
window.setTimeout(function(){startDownloadMonitoring()}, 3000);
window.setTimeout(function(){startDownloadMonitoring()}, 5000);
window.setTimeout(function(){startDownloadMonitoring()}, 7000);
window.setTimeout(function(){startDownloadMonitoring()}, 9000);
};
// call monitoring PHP script via AJAX
function startDownloadMonitoring()
{
console.log("Calling startDownloadMonitoring()...");
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
console.log("Response Received: " + xmlhttp.responseText);
}
}
xmlhttp.open("GET", "PHP/fileDownloadStatus.php", true);
xmlhttp.send();
}
</script>
</body>
</html>
PHP Monitoring Script(fileDownloadStatus.php)
<?php
include 'ChromePhp.php';
// start session, update session variable, close session
session_start();
$_SESSION['DownloadProgress']++;
ChromePhp::log('$_SESSION[\'DownloadProgress\'] = ' . $_SESSION['DownloadProgress']);
session_write_close();
echo "success";
?>
PHP long-running script (fileDownload.php)
<?php
include 'ChromePhp.php';
// disable script expiry
set_time_limit(0);
// start session, define variable, close session
session_start();
// prepare session variables
$_SESSION['DownloadProgress'] = 10;
session_write_close();
// execute for 60 seconds
for( $count = 0; $count < 60; $count++)
{
sleep(1);
}
?>
The first script it's not send through ajax:
// run long running (later Download) PHP script
console.log("Calling: PHP/fileDownload.php");
window.location.href = 'PHP/fileDownload.php';
You simply redirect the user to another page, and because you have download headers in php, the file is downloaded in the same page.
You can easily achieve your scope through an iframe. You set the source of that iframe : 'PHP/fileDownload.php' and then simply call your ajax download checker.
Short example:
<iframe src="PHP/fileDownload.php">
<script>
window.setTimeout(function(){startDownloadMonitoring()}, 1000);
window.setTimeout(function(){startDownloadMonitoring()}, 3000);
window.setTimeout(function(){startDownloadMonitoring()}, 5000);
window.setTimeout(function(){startDownloadMonitoring()}, 7000);
window.setTimeout(function(){startDownloadMonitoring()}, 9000);
// .... blah blah
</script>
When you call
window.location.href = 'PHP/fileDownload.php';
the script execution stops (not immediately, see https://stackoverflow.com/a/2536815/2806497).
Are you sure ajax calls to fileDownloadStatus.php are executed ?
A solution would be to call the fileDownloadStatus.php file by an ajax asynchronous call, or maybe to load it into an iframe you put in your page.
Hope that helps.
I am pretty new to creating web applications, so I am very unfamiliar with working over a web server. Just to let everyone know, I am implementing html, javascript, strawberry perl, AJAX, and running over an APACHE 2 web server. I finally have my web app working, I have an html file that calls a perl script that is in my htdocs directory. Here is a mock up of my .html file for reference, this one simply alerts the user of the output printed by the perl script:
<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDoc() {
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
var str;
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
// Get output from perl script and print it
str = xmlhttp.responseText;
alert(str);
}
}
xmlhttp.open("GET","http://localhost/try.pl" , false); //perl script
xmlhttp.send();
}
</script>
</head>
<body>
<h2>Example</h2></div>
<button type="button" onclick="loadXMLDoc()">Display</button>
</body>
</html>
So this file test.html calls a perl script [try.pl] within the same directory. Also, the perl script just prints a number so this alerts the user of the number. This is just an example of my implementation. My actual perl script and java script [inside the ready state block] is much more complicated. Now I have to add functionality to my web app, so to my questions:
I am looking to run a second and separate perl script when a different event happens. For example, when a button is clicked this perl script is being ran. I am going to have another different event, say a double click on an icon or something, that will need to call this second perl script. Will I simply have the new event call a different function [the first is called Loadxmldoc()] that is almost identical to the one I have here except it will have different code in the ready state block and call a different perl script at the end of it? I am a little confused as to how to implement this.
Also, If I have a list of file names within my javascript code, I need to process EACH of the files using a perl script. Currently I am only processing one so calling the perl script as I have here is fine. I have looked all over the internet to try to find how I would do this but it seems every explanation just covers how to call "a" CGI script. So within my code, say where I am "alerting" the user, I am going to have an array that stores the file names. I need to iterate over this array and for each filename [array element] I need to call the same perl script to process that file. How should I go about implementing this? Currently, my html file is only calling the perl script once and I do not know how I could call it for EACH file since my GET command is outside of my ready state block...
Any help or direction would be appreciated. I am expected to deliver soon and have been spending way too much time sifting through repetitive examples that haven't helped me...:/
As far as generalizing your AJAX request, you can create a function (or rather, a set of functions) that would process different types of responses, as follows:
var requests = [];
requests['script1'] = "http://localhost/try.pl";
requests['script2'] = "http://localhost/try2.pl";
var response_processing = [];
response_processing['script1'] = function (xmlhttp) {
var str = xmlhttp.responseText;
alert(str);
};
// Here, you can add more functions to do response processing for other AJAX calls,
under different map keys.
Now, in your AJAX code, you call an appropriate request AND appropriate response processor, based on your script name (passed to loadXMLDoc() call as follows): loadXMLDoc("script1");
function loadXMLDoc(script_name) {
// Your generic AJAX code as you already implemented
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
response_processing[script_name](xmlhttp);
// Careful so script_name doesn't get closured in onreadystatechange()
}
}
xmlhttp.open("GET", requests[script_name], false); //perl script
xmlhttp.send();
}