PDA

View Full Version : Function won't repeat



kasei
12-29-2007, 05:40 PM
I'm trying to get this function to repeat once every second.

It's supposed to:
1. copy the text off of the webpage
2. split it at the '|'
3. add the second string to the document
4. replace the variable in the function's bracket with the first string from the split
5. and repeat the process after 1000 miliseconds.


function getPage(t) {
var xmlhttp=false;
try {
xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xmlhttp = new
ActiveXObject('Microsoft.XMLHTTP');
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}

var file = 'http://webpage.com/page.php?t=';
xmlhttp.open('GET', file + t, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
var content = xmlhttp.responseText;
var bit = content.split("|");
document.getElementById('text').innerHTML += bit[1];
}
}
xmlhttp.send(null);
return;
r=setTimeout("getPage(bit[0])",1000);
}


Everything seems to work fine until it's time to repeat. Then I get an error that says 't' is undefined

Trinithis
12-29-2007, 06:44 PM
You need to place the return statement after the timeout.

tech_support
12-30-2007, 12:46 AM
And bit[0] needs to be outside of the string, like this:


r=setTimeout("getPage('"+bit[0]+"')",1000);

jscheuer1
12-30-2007, 12:54 AM
Or, the way real coders do it:


r=setTimeout(function(){getPage(bit[0]);},1000);

What's r?

Twey
12-30-2007, 03:00 AM
Or, the way real coders do it:Or sane people. :)
What's r?A numerical identifier for the timeout request (used with clearTimeout() &c.).

Neither of these solutions will work, of course, because "bit" is local to the onchange function.
var Xhr = (function() {
var xhr = null;

function newXhr() {
if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if(window.ActiveXObject)
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}

function getXhr() {
return xhr || (xhr = newXhr());
}

function getFile(url, callback) {
var xhr = getXhr();
xhr.open("GET", url, !!callback);
if(callback)
xhr.onreadystatechange = function() {
if(this.readyState === 4)
return callback(this.responseText);
};
xhr.send(null);
return callback ? undefined : xhr.responseText;
}

return {
newXhr: newXhr,
getXhr: getXhr,
getFile: getFile
};
})();

// I'm not sure what this function should be called, but
// "getPage" is woefully inaccurate.
function awakenLateParrot(t) {
Xhr.getFile("http://webpage.com/page.php" + (t ? "?t=" + t : ""),
function(text) {
// Hurry up o ye days of destructuring assignment and
// (nextT, toAppend) = text.split("|"); // :-(
var nextT = text.split("|"),
toAppend = nextT[1];
nextT = nextT[0];

document.getElementById("text").appendChild(document.createTextNode(toAppend));
setTimeout(function() { awakenLateParrot(nextT); }, 1000);
});
}

Trinithis
12-30-2007, 03:22 AM
A numerical identifier for the timeout request (used with clearTimeout() &c.).

Numerical? Don't you mean alphabetic?

Twey
12-30-2007, 03:35 AM
No, numerical. It's an integer.

jscheuer1
12-30-2007, 04:15 AM
Yes, r would be a number, but it is undeclared and in the global scope, so it's an error waiting to happen. I asked what it was to get at that fact, not because I didn't know what sort of value it would (if unencumbered by errors) be assigned.

kasei
12-30-2007, 12:46 PM
What's r?

I don't know... I'm pretty weak on JavaScript, but I'm trying to learn. I just used what I saw on www.w3schools.com to see if I could splice it together and make it work.


<html>
<head>
<script type="text/javascript">
function timedMsg()
{
var t=setTimeout("alert('5 seconds!')",5000);
}
</script>
</head><body>
<form>
<input type="button" value="Display timed alertbox!"
onClick="timedMsg()">
</form>
</body>
</html>

In this case, I just took the function and replaced t (which is also undeclared, isn't it?) with r since I was already using t as a variable at the time.

Thank you Twey, that seems to fix that problem. Onto the next bug... :p

kasei
12-30-2007, 01:51 PM
Well...

I don't get any more errors, but it doesn't display anything at all now!


<html>
<head>
<title>Test</title>

<script type="text/javascript">
var Xhr = (function() {
var xhr = null;

function newXhr() {
if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if(window.ActiveXObject)
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}

function getXhr() {
return xhr || (xhr = newXhr());
}

function getFile(url, callback) {
var xhr = getXhr();
xhr.open("GET", url, !!callback);
if(callback)
xhr.onreadystatechange = function() {
if(this.readyState === 4)
return callback(this.responseText);
};
xhr.send(null);
return callback ? undefined : xhr.responseText;
}

return {
newXhr: newXhr,
getXhr: getXhr,
getFile: getFile
};
})();

// I'm not sure what this function should be called, but
// "getPage" is woefully inaccurate.
function awakenLateParrot(t) {
Xhr.getFile("http://test.game.joescuriosityshoppe.com/chat/getposts.php" + (t ? "?t=" + t : ""),
function(text) {
// Hurry up o ye days of destructuring assignment and
// (nextT, toAppend) = text.split("|"); // :-(
var nextT = text.split("|"),
toAppend = nextT[1];
nextT = nextT[0];

document.getElementById("text").appendChild(document.createTextNode(toAppend));
setTimeout(function() { awakenLateParrot(nextT); }, 1000);
});
}
</script>

</head>
<body onload="awakenLateParrot('0')">
<div id="text"></div>
</body>
</html>

I've set getposts.php to display a 4 character number, followed by "|<div>hello</div>", no matter if t has any value at all.

If it worked, then "hello" should be displayed and the function should repeat after 1000 miliseconds with the 4 character number as the new t, right?

All I get is a blank screen. :confused:

jscheuer1
12-30-2007, 04:54 PM
You will have to excuse Twey, he rarely tests his code, even for something complex like this, and often radically alters what is given in the posts.

That may or may not have anything to do with what happened here.

Anyways, altering as little as possible, I got this to work:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function getPage(t) {
if (typeof getPage.n!='number')
getPage.n=0;
var xmlhttp=false;
try {
xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xmlhttp = new
ActiveXObject('Microsoft.XMLHTTP');
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}

var file = '';//'http://webpage.com/page.php?t=';
xmlhttp.open('GET', file + t, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
var content = xmlhttp.responseText;
var bit = content.split("|");
if(bit && getPage.n<bit.length)
document.getElementById('text').innerHTML += bit[getPage.n++];
else
return;
setTimeout(function(){getPage(t);},1000);
}
}
xmlhttp.send(null);
}
</script>
</head>
<body>
<div id="text">

</div>
<input type="button" onclick="getPage('text.htm');">
</body>
</html>

In FF and IE using this file as text.htm:


Hi<br>|There<br>|Ladies<br>|and<br>|Gentlemen!

I was puzzled with and realized it would never work locally, and so commented out this bit (changed it to an empty string):


'http://webpage.com/page.php?t=';

That could perhaps work on a PHP enabled server. With my working example, the code is more repetitive than need be and generally poorly written. I didn't worry about that much, but for example - the array could be gotten just once.

However, if the page fetched keeps changing instead of the position in the array, things would need to be a 'bit' different.

kasei
12-30-2007, 08:19 PM
Yes, thankyou.

I also rarely test my scripts when I help people with PHP (though it's never this complex! :p ).

I'm very grateful for the help that everybody's given me on this problem.:D

And, yes, the purpose of this script is to take a small chunk of text off of a website that is constantly updated based on the t variable in the URL, which is why I wanted it to repeat in an infinant loop.

If I'm not mistaken, the way you have it set up here it will either write the text to the page or try again if nothing is there. right?

If I wanted it to repeat even if the function succeeded, do I change:

if(bit && getPage.n<bit.length)
document.getElementById('text').innerHTML += bit[getPage.n++];
else
return;
setTimeout(function(){getPage(t);},1000);


to:


document.getElementById('text').innerHTML += bit[getPage.n++];
setTimeout(function(){getPage(t);},1000); // This comes before the return, right?
return;


or is this right?


if(bit && getPage.n<bit.length) document.getElementById('text').innerHTML += bit[getPage.n++];

setTimeout(function(){getPage(t);},1000);
return;

Twey
12-31-2007, 12:36 AM
Since it uses an XHR request to your domain, it's quite hard to test. Could you set up a demo page?

Also, you did call the function, correct?

jscheuer1
12-31-2007, 06:13 AM
If I'm not mistaken, the way you have it set up here it will either write the text to the page or try again if nothing is there. right?

Not quite. Since I had a finite page with finite content, I wrote it to write what was available in 1 second increments and then quit.

What would the typical xmlhttp.responseText look like under your setup?

I think the basic intent of your function could be carried out like so:


function getPage(t) {
var xmlhttp=false;
try {
xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xmlhttp = new
ActiveXObject('Microsoft.XMLHTTP');
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}

var file = 'http://webpage.com/page.php?t=';
xmlhttp.open('GET', file + t, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
var content = xmlhttp.responseText;
var bit = content.split("|");
document.getElementById('text').innerHTML += bit[1];
setTimeout(function(){getPage(bit[0]);},1000);
}
}
xmlhttp.send(null);
}

But, it would depend upon there being a bit[1] and a bit[0] each time, which in turn depends upon what I asked about - the xmlhttp.responseText. And more crucially upon whether or not the string contained in bit[0] would be a valid argument for the next loop (a valid query string value for http://webpage.com/page.php?t=).

Twey
12-31-2007, 07:11 AM
My code would be preferable if we can get it working.

kasei
12-31-2007, 03:07 PM
What would the typical xmlhttp.responseText look like under your setup?

[SNIP]

But, it would depend upon there being a bit[1] and a bit[0] each time, which in turn depends upon what I asked about - the xmlhttp.responseText. And more crucially upon whether or not the string contained in bit[0] would be a valid argument for the next loop (a valid query string value for http://webpage.com/page.php?t=).

The page would return a number|message, the number being generated with PHP's date() function. There would always be a bit[0], and it'd always be a 6 digit number, but there might not always be a bit[1].

jscheuer1
12-31-2007, 03:22 PM
Then you would want to add (red):


if (xmlhttp.readyState==4) {
var content = xmlhttp.responseText;
var bit = content.split("|");
if(bit[1])
document.getElementById('text').innerHTML += bit[1];
setTimeout(function(){getPage(bit[0]);},1000);
}
}

And this raises another question, when and if there is no bit[1], does this herald the end? I mean, once this happens, is it no longer possible that running the function for more loops will ever produce a bit[1]? Must we wait until conditions have changed to try again, or will continued looping at this point find a result for bit[1] on some random or other basis in a reasonable amount of time? If we are finished the first time bit[1] is undefined, you should do this:


if (xmlhttp.readyState==4) {
var content = xmlhttp.responseText;
var bit = content.split("|");
if(bit[1]){
document.getElementById('text').innerHTML += bit[1];
setTimeout(function(){getPage(bit[0]);},1000);
}
}
}

kasei
12-31-2007, 07:09 PM
Since it uses an XHR request to your domain, it's quite hard to test. Could you set up a demo page?

Here you go:
http://test.game.joescuriosityshoppe.com/chat/index.php

I've included an iframe to the page that the function is stripping the text from below the chat box. The bottom iframe should automatically reload if you click on the button. :P


if there is no bit[1], does this herald the end?

No, this is for a chat box, so I want it to keep checking for new messages until the user closes the window.


My code would be preferable if we can get it working.

I'm sure it would. I hope I can kick my brain into gear and figure out what I'm doing wrong.

jscheuer1
12-31-2007, 07:43 PM
Well, if you want to keep going, skip the second part of my last post. There is an error on your demo:


<script type="text/javascript">
function reloadiframe() {
var f = document.getElementById('test');
f.contentWindow.location.reload(true);
msg.value=''
}
</script>


<iframe src="getposts.php?t=0.0" name="test"

Twey
12-31-2007, 09:13 PM
I'm sure it would. I hope I can kick my brain into gear and figure out what I'm doing wrong.When I said a demo page I meant using that code.