I need help figuring out how i can setInterval while keeping a "str" to the function.
The client chooses an option, and the function "GET"'s the selected option.. But when it refreshes in setInterval, it looses the string.. How can i do this?
I have tried this:
<script type="text/javascript">
function countrystats(str)
{
if (str=="")
{
document.getElementById("countrystats").innerHTML="";
return;
}
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("countrystats").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","countrystats.php?q="+str,true);
xmlhttp.send();
setInterval(countrystats, 5000);
}
</script>
Hopefully you can help me sort out this mess :-)
I am aware that this can be done with some jQuery, but i cat seem to get that to work. Maybe those two things are related, i dont know :-)
Here is how the function countrystats gets its input:
script type="text/javascript">
$("#countrystats_menu > li > a").click(function (ev) {
var str = $(this).html();
countrystats(str);
$('#country_span').html(str);
});
</script>
EDIT/Solution:
It seems that the problem was, when doing setInterval, it looses the str attached, this code is however preserving it.
setTimeout((function(strPriorToTimeout)
{//IIFE's scope preserves state of str variable
return function()
{
countrystats(strPriorToTimeout);
};
})(str),5000);
The argument str goes out of scope at the end, the interval simply calls the function without passing any value to str. As some comments suggest, countrystats(str) would appear to do the trick, but it doesn't, here's why:
setInterval(countrystats(str), 500);
This line contains multiple expressions that will be evaluated/resolved to some value, like countrystats(str), which is a direct call to a function. The function, then, will be called prior to the interval being set. The quickest solution is creating an anonymous function, and call the function from within:
setInterval(function()
{
countrystats(str);
},5000);
You can even play it extra safe, by creating a closure, actually passing the intended value of str to the interval function. This is optional, and might look a bit confusing (and messy):
setInterval((function(strPriorToTimeout)
{//IIFE's scope preserves state of str variable
return function()
{
countrystats(strPriorToTimeout);
};
})(str),5000);
There is just one thing that's bothering me about your code: you're using setInterval, which repeats the same function call every X ms. If you only need to call a function once, it might be better using setTimeout.
Another thing is: setInterval returns the interval's id, so you can stop the constant function calls if needed. You don't seem to be assigning that ID anywhere, so your code will keep on running, unless you're brute-forcing the clearInterval calls. Perhaps consider assigning the return value of setInterval to some variable you can access.
If you don't the only way of clearing intervals AFAIK would be:
for (var i=0;i<Number.MAX_VALUE;i++)
{
clearInterval(i);
}
Now that's just terrible, isn't it?
In light of the comments, I thought I'd do well adding some info on webworkers here. From what I gather the OP wants to acchieve, I recommended using webworkers as much as possible. A basic setup here could be:
//client.js
var worker = new Worker('dashWorker.js');//worker script
//to kick off the worker:
function countrystats(str)
{
str = str || document.getElementById('countrystats').innerHTML;//get str value
worker.postMessage(str);//that's it, the worker takes care of everything else
}
worker.onmessage = function(response)
{
document.getElementById('countrystats').innerHTML = response.response;//cf worker code
return countrystats(response.str);//choose when to call the countrystats function again, as soon as the worker responded... easy!
};
//the worker:
self.onmessage = function(e)
{//you could add a way of stopping the constant updates, by posting a 'stopDash' or something...
//do ajax call using e.data --> this is the string anyhow
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(response)
{
if (this.readyState === 4 && this.status === 200)
{
self.postMessage({str: e.data,
response: response.responseText});
}
};
xhr.open('GET', 'countrystats.php?q=' + e.data,true);
xhr.send();
};
Of course, this code is far from "clean": it could do with some performance tweaks (like not querying the DOM all the time), but the basic principal stands...
A couple of important links for you here:
MDN
John Resig's blog post on workers
A step-by-step introduction to webworkers
you are calling setInterval(countrystats, 5000); in the same function. you can do with jquery also
url='countrystats.php?q='+str;
ajax calll
$.get(url, function(data) {
$('#countrystats').html(data);
});
once the get finishes. you can call setInterval(countrystats, 5000); for refreshing the content.
I've simplified your code with jQuery. I've used jQuery.load to load the remote html to the start element.
And whenever a new item is clicked you need to create the previous interval, otherwise multiple request threads will be running
function countrystats(str) {
if (str == "") {
$('#countrystats').empty();
return;
}
$('#countrystats').load('countrystats.php?q=' + str)
}
var interval;
$("#countrystats_menu > li > a").click(function(ev) {
if (interval) {
clearInterval(interval);
}
var str = $(this).html();
countrystats(str);
interval = setInterval(function() {
countrystats(str);
}, 5000);
$('#country_span').html(str);
});
Related
I'm trying to get a page with AJAX, but when I get that page and it includes Javascript code - it doesn't execute it.
Why?
Simple code in my ajax page:
<script type="text/javascript">
alert("Hello");
</script>
...and it doesn't execute it. I'm trying to use Google Maps API and add markers with AJAX, so whenever I add one I execute a AJAX page that gets the new marker, stores it in a database and should add the marker "dynamically" to the map.
But since I can't execute a single javascript function this way, what do I do?
Is my functions that I've defined on the page beforehand protected or private?
** UPDATED WITH AJAX FUNCTION **
function ajaxExecute(id, link, query)
{
if (query != null)
{
query = query.replace("amp;", "");
}
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)
{
if (id != null)
{
document.getElementById(id).innerHTML=xmlhttp.responseText;
}
}
}
if (query == null)
{
xmlhttp.open("GET",link,true);
}
else
{
if (query.substr(0, 1) != "?")
{
xmlhttp.open("GET",link+"?"+query,true);
}
else
{
xmlhttp.open("GET",link+query,true);
}
}
xmlhttp.send();
}
** Solution by Deukalion **
var content = xmlhttp.responseText;
if (id != null)
{
document.getElementById(id).innerHTML=content;
var script = content.match("<script[^>]*>[^<]*</script>");
if (script != null)
{
script = script.toString().replace('<script type="text/javascript">', '');
script = script.replace('</script>', '');
eval(script);
}
}
and on certain events, I had to within the script addevent listeners instead of just making a "select onchange='executeFunctionNotIncludedInAjaxFile();'" I had to addEventListener("change", functionName, false) for this. In the script that is being evaluated.
When you update your page by doing something like setting a container's innerHTML to some updated content, the browser simply will not run the scripts in it. You can locate the <script> tags, get their innerHTML (IE may prefer innerTEXT), and then eval() the scripts yourself (which is pretty much what jQuery does, though it finds the scripts with a regex before updating the DOM).
Use this function:
function parseScript(_source) {
var source = _source;
var scripts = new Array();
// Strip out tags
while(source.indexOf("<script") > -1 || source.indexOf("</script") > -1) {
var s = source.indexOf("<script");
var s_e = source.indexOf(">", s);
var e = source.indexOf("</script", s);
var e_e = source.indexOf(">", e);
// Add to scripts array
scripts.push(source.substring(s_e+1, e));
// Strip from source
source = source.substring(0, s) + source.substring(e_e+1);
}
// Loop through every script collected and eval it
for(var i=0; i<scripts.length; i++) {
try {
eval(scripts[i]);
}
catch(ex) {
// do what you want here when a script fails
}
}
// Return the cleaned source
return source;
}
then do parseScript(xmlhttp.responseText); when you're replacing/adding content.
In case some other people stumble upon this old thread, there is one issue with the accepted answer by Deukalion, there is one issue that may have been overlooked: as written, the script only looks for the first script tag. If multiple script tags exist, all others are overlooked.
A few minor tweaks would resolve the issue. Change one line from:
var script = content.match("<script[^>]*>[^<]*</script>");
To:
var script = content.match(/<script[^>]*>[^<]*<\/script>/g);
And another from:
script = script.toString().replace('<script type="text/javascript">', '');
To:
script = script.join("").replace(/<script type="text\/javascript">/g, '');
Now it will gather all the <script> code and execute them in the order found on the page. Otherwise it was an excellent solution.
After the AJAX request, you can make an "on success" function which can take the returned html and do something with it. Then something will be executed.
If there was a code example, then I could provide a code solution to the situation. But using just standard xmlhttprequest, the following could be done:
xhr = new XMLHttpRequest();
xhr.open("GET","ajax_info.txt",true);
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200)
{
document.getElementById("myDiv").innerHTML = xhr.responseText;
}
}
xhr.send();
I think I'm getting ahead of myself, but I tried AJAX tutorials to read from a PHP file. The PHP file simply has an echo statement for the time, and I want to pass that to initialize a javascript clock.
But this is my first time trying AJAX and I can't even seem to get it to activate a test alert message.
Here is the code, it's at the bottom of my PHP page after all of the PHP.
<script type='text/javascript'>
function CheckForChange(){
//alert("4 and 4");
//if (4 == 1){
//setInterval("alert('Yup, it is 1')", 5000);
//alert('Now it is changed');
//}
var ajaxReady = new XMLHttpRequest();
ajaxReady.onreadystatechange = function(){
if (ajaxReady.readystate == 4){
//Get the data
//document.getElementById('clocktxt').innerHTML = ajaxReady.responseText;
alert("here");
alert(ajaxReady.responseText);
}
}
ajaxReady.open("GET","ServerTime.php",true);
ajaxReady.send(null);
}
setInterval("CheckForChange()", 7000);
</script>
Can somebody tell me why this isn't working? No idea what I'm doing wrong.
The problem in your code is an uncapitalized letter. (Oops!) You check ajaxReady.readystate; you need to check ajaxReady.readyState.
Because ajaxReady.readystate will always be undefined, your alerts never fire.
Here's your code fixed and working.
As an aside, have you considered using a library to handle the ugliness of cross-browser XHR? jQuery is your friend:
function CheckForChange(){
$.get('ServerTime.php', function(data) {
$('#clocktxt').text(data);
});
}
You should probably have something like:
setInterval(CheckForChange, 7000);
On an unrelated note, it's common naming convension in JavaScript to have function and methods names' first letters not capitalized, and the rest is in camelCase. i.e. checkForChange().
I'm not sure the exact problem with your code; here's what I use -- I'm sure it will work for you. (plus, it works with more browsers)
var xhr = false;
function CheckForChange(){
/* Create xhr, which is the making of the object to request an external file */
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
if(window.ActiveXObject){
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){}
}
}
/* End creating xhr */
/* Retrieve external file, and go to a function once its loading state has changed. */
if(xhr){
xhr.onreadystatechange = showContents;
xhr.open("GET", "ServerTime.php", true);
xhr.send(null);
}else{
//XMLHTTPRequest was never created. Can create an alert box if wanted.
}
/* End retrieve external file. */
}
function showContents(){
if(xhr.readyState==4){
if(xhr.status==200){
alert(xhr.responseText);
}else{
//Error. Can create an alert box if wanted.
}
}
}
setInterval(CheckForChange, 7000);
While developing a web app where I'm making great use of javascript php and ajax.
I want to call
display_terminal('feedback_viewer','logs/init-raid-log.txt','Init-Raid');
to build my terminal and call feed_terminal() which has its own setTimeout() recursion call
var url='../edit_initRaid.php';
status_text('Initializing raid-array. Please wait a moment...');
var xmldoc=ajaxPHP2(url,2);
a php file that does nothing more that
exec("sudo /usr/bin/./init-raid-drives-web.sh");
and this is where I fail. This next line is not executed until after the exec() in the php file returns to the php file and the php file returns to the javascript. Not that it matters, but I am pretty sure it did not used to be this way, as originally the bash script would execute over a time period of 2 minutes and the javascript would successfully be updating the html with feed_terminal. this is not the case anymore.
alert("javascript has returned from ajax call");
if (xmldoc) {
status_text('Raid-array initialized successfully. System will now restart.You must re-login to FDAS-Web.');
Below is a bunch of code for your questions
Ultimately my question is, how can I run javascript DURING the ajax call?
Or maybe my question should be, how can I have edit_initRaid return an xmldoc, without waiting for the exec() to return, or how can i have the exec() return even without the script completing?
function initRaidArray(){
if (document.getElementById('initRaid_doubleCheck')){
if (document.getElementById('initRaidHideButtonSpot'))
document.getElementById('initRaidHideButtonSpot').innerHTML = '';
var spot=document.getElementById('initRaid_doubleCheck');
spot.innerHTML='';
spot.innerHTML='This may take a few moments. Please wait.';
}
display_terminal('feedback_viewer','logs/init-raid-log.txt','Init-Raid');
var url='../edit_initRaid.php';
status_text('Initializing raid-array. Please wait a moment...');
var xmldoc=ajaxPHP2(url,2);
alert("javascript has returned from ajax call");
if (xmldoc) {
status_text('Raid-array initialized successfully. System will now restart. You must re-login to FDAS-Web.');
}
}
where display_terminal() does two things, builds a table and appends it to the page, and calls feed_terminal(logfile,bigDiv,0)
function feed_terminal(logFile,bigD,lap){
// AJAX
bigD.innerHTML = '';
var url='../view_xml_text.php';
/*
* lap(0)=clear file , lap(1)=do not clear file
*/
url+='?logFile='+logFile+'&lap='+lap;
var XMLdoc=ajaxPHP2(url,2);
var xmlrows = XMLdoc.getElementsByTagName("line");
alert("xmlrows.length=="+xmlrows.length);
// empty file
if (xmlrows.length==0){
var d = document.createElement('div');
var s = document.createElement('span');
s.innerHTML='...';
d.appendChild(s);
bigD.appendChild(d);
} else {
// Parse XML
for (var i=0;i<xmlrows.length;i++){
if (xmlrows[i].childNodes[0]){
if (xmlrows[i].childNodes[0].nodeValue){
var d = document.createElement('div');
var s = document.createElement('span');
s.innerHTML=xmlrows[i].childNodes[0].nodeValue;
d.appendChild(s);
bigD.appendChild(d);
}
}
}
}
setTimeout(function(){feed_terminal(logFile,bigD,1)},2000);
}
where the most important item is the setTimeout() call to continue reaching out to the php file which returns xml of the lines in the file, simply.
function ajaxPHP2(url,key)
{
if (window.XMLHttpRequest) {
xml_HTTP=new XMLHttpRequest();
if (xml_HTTP.overrideMimeType) {xml_HTTP.overrideMimeType('text/xml');}
} else { xml_HTTP=new ActiveXObject("Microsoft.xml_HTTP"); }
xml_HTTP.open("GET",url,false);
xml_HTTP.send(null);
if (key){return xml_HTTP.responseXML;}
}
You need to tell Javascript to do your XHR call asynchronously.
Change
xml_HTTP.open("GET",url,false);
to
xml_HTTP.open("GET",url,true);
But first, you'll need to tell it to do something when the request completes (a callback):
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert(xmlhttp.responseText);
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send();
One recommendation: XHR is a pain. It would be a lot easier to use something like jQuery's $.ajax()
You need to set your ajax call to be asynchronous. In the ajaxPHP2 function, the line xml_HTTP.open("GET", url, false); is what is causing the page to pause. The false parameter is telling the ajax call to make everything else wait for it. Change the false to true so it looks like this:
xml_HTTP.open("GET", url, true);
You may also need to attach a function to the onreadystatechange property so that when the ajax call returns it knows what to do. See these links for more information.
I have a little script which uses AJAX and PHP to display an image. You can see below that if I call the function mom() it looks in the PHP file index.php?i=mom and displays the image I'm looking for.
But I need the javascript to be lighter as I have 30 images and for each one I have to modify and copy the script below. Is there not a simpler way to have the functions be different and still call a different page?
<script type="text/javascript">
function mom()
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse(xmlHttp.responseText);
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
function HandleResponse(response)
{
document.getElementById('mom').innerHTML = response;
}
</script>
My Trigger is this
<a href="#" onclick='mom();' />Mom</a>
<div id='mom'></div>
You could modify your function so it takes a parameter :
// The function receives the value it should pass to the server
function my_func(param)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
// Pass the received value to the handler
HandleResponse(param, xmlHttp.responseText);
}
}
// Send to the server the value that was passed as a parameter
xmlHttp.open("GET", "index.php?i=" + param, true);
xmlHttp.send(null);
}
And, of course, use that parameter in the second function :
function HandleResponse(param, response)
{
// The handler gets the param too -- and, so, knows where to inject the response
document.getElementById(param).innerHTML = response;
}
And modify your HTML so the function is called with the right parameter :
<!-- for this first call, you'll want the function to work on 'mom' -->
<a href="#" onclick="my_func('mom');" />Mom</a>
<div id='mom'></div>
<!-- for this secondcall, you'll want the function to work on 'blah' -->
<a href="#" onclick="my_func('blah');" />Blah</a>
<div id='blah'></div>
This should work (if I understand correctly)
<script type="text/javascript">
function func(imgName)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
document.getElementById(imgName).innerHTML =
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
</script>
MARTIN's solution will work perfectly.
By the way you should use some javascript framework for Ajax handling like jQuery.
It will make your life easy.
If you are having light weight images you preload the images on your page.
I solved this by making an array of in your case xmlHttp and a global variable, so it increments for each request. Then if you repeatedly make calls to the same thing (eg it returns online users, or, whatever) then you can actually resubmit using the same element of the array too.
Added example code:
To convert it to a reoccuring event, make a copy of these 2, and in the got data call, just resubmit using reget
var req_fifo=Array();
var eleID=Array();
var i=0;
function GetAsyncData(myid,url) {
eleID[i]=myid;
if (window.XMLHttpRequest)
{
req_fifo[i] = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
req_fifo[i] = new ActiveXObject("Microsoft.XMLHTTP");
}
req_fifo[i].abort();
req_fifo[i].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(i);
req_fifo[i].open("GET", url, true);
req_fifo[i].send(null);
i++;
}
function GotAsyncData(id) {
if (req_fifo[id].readyState != 4 || req_fifo[id].status != 200) {
return;
}
document.getElementById(eleID[id]).innerHTML=
req_fifo[id].responseText;
req_fifo[id]=null;
eleID[id]=null;
return;
}
function reget(id) {
myid=eleID[id];
url=urlID[id];
req_fifo[id].abort();
req_fifo[id].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(id);
req_fifo[id].open("GET", url, true);
req_fifo[id].send(null);
}
The suggestions to parameterize your function are correct and would allow you to avoid repeating code.
the jQuery library is also worth considering. http://jquery.com
If you use jQuery, each ajax call would literally be this easy.
$('#mom').load('/index.php?i=mom');
And you could wrap it up as follows if you'd like, since you say you'll be using it many times (and that you want it done when a link is clicked)
function doAjax(imgForAjax) { $('#'+imgForAjax).load('/index.php&i='+imgForAjax);}
doAjax('mom');
It makes the oft-repeated ajax patterns much simpler, and handles the issues between different browsers just as I presume your getXMLhttp function does.
At the website I linked above you can download the library's single 29kb file so you can use it on your pages with a simple <script src='jquery.min.js'></script> There is also a lot of great documentaiton. jQuery is pretty popular and you'll see it has a lot of questions and stuff on SO. ajax is just one of many things that jQuery library/framework (idk the preferred term) can help with.
I want to know is it possible to call a php function within javascript, only and only when a condition is true. For example
<script type="text/javascript">
if (foo==bar)
{
phpFunction(); call the php function
}
</script>
Is there any means of doing this.. If so let me know. Thanks
PHP is server side and Javascript is client so not really (yes I know there is some server side JS). What you could do is use Ajax and make a call to a PHP page to get some results.
The PHP function cannot be called in the way that you have illustrated above. However you can call a PHP script using AJAX, code is as shown below. Also you can find a simple example here. Let me know if you need further clarification
Using Jquery
<script type="text/javascript" src="./jquery-1.4.2.js"></script>
<script type="text/javascript">
function compute() {
var params="session=123";
$.post('myphpscript.php',params,function(data){
alert(data);//for testing if data is being fetched
var myObject = eval('(' + data + ')');
document.getElementById("result").value=myObject(addend_1,addend_2);
});
}
</script>
Barebones Javascript Alternative
<script type="text/javascript">
function compute() {
var params="session=123"
var xmlHttp;
var addend_1=document.getElementById("par_1").value;
var addend_2=document.getElementById("par_2").value;
try
{
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
try
{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert("No Ajax for YOU!");
return false;
}
}
}
xmlHttp.onreadystatechange = function()
{
if (xmlHttp.readyState == 4) {
ret_value=xmlHttp.responseText;
var myObject = eval('(' + ret_value + ')');
document.getElementById("result").value=myObject(addend_1,addend_2);
}
}
xmlHttp.open("POST", "http://yoururl/getjs.php", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("Content-length", params.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.send(params);
}
</script>
No that's not possible. PHP code runs before (server-side) javascript (client-side)
The other answers have it right.
However, there is a library, XAJAX, that helps simulate the act of calling a PHP function from JavaScript, using AJAX and a particularly designed PHP library.
It's a little complicated, and it would be much easier to learn to use $.get and $.post in jQuery, since they are better designed and simpler, and once you get your head around how they work, you won't feel the need to call PHP from JavaScript directly.
PHP always runs before the page loads. JavaScript always runs after the page loads. They never run in tandem.
The closest solution is to use AJAX or a browser redirect to call another .php file from the server.