• 0

[JS] Simple function not working unless I do alert() first


Question

The following code divides 'invites' by 'accepts' and then rounds it to 2 decimal places, always keeping 2 decimal places even if the answer is 8.00

This is the code I am using:

function live_ratio()
{
	// Check that the invites, accepts, and ratio spans have loaded
	while(!document.getElementById("live_invites").innerHTML || !document.getElementById("live_accepts").innerHTML || !document.getElementById("live_ratio").innerHTML)
	{
		//alert('blah');
		document.getElementById("live_ratio").innerHTML = (Math.round(document.getElementById("live_invites").innerHTML / document.getElementById("live_accepts").innerHTML * 100) / 100).toFixed(2);
	}
}

For some reason, it doesn't work how it is now, it just doesn't invoke the document.getElementById("live_ratio").innerHTML line, and doesn't update the span. However, if I uncomment the alert() above, it works perfectly! :blink: Any ideas? Also, it has to be in the while() statement because the 3 id's it checks have loaded, are loaded via AJAX.

Thanks all!

13 answers to this question

Recommended Posts

  • 0

someone at work was having the same problem a couple of weeks ago. remember that ajax is asynchronous and other executions will continue to be processed before the ajax stuff comes back. the alert is stopping execution of those 'other' tasks and the ajax finishes before you click ok. im not 100% sure that's your problem but it's eerily similar to what a saw a couple weeks ago.

  • 0

The function posted above though is nothing to do with the AJAX function I have, and I am not even calling the function from my AJAX function, I'm just doing a standalone live_ratio(); call.

...And either way, if that was the case, surely it would continue to loop through the while() until my spans had loaded?

  • 0

i created a page, added those three elements to the page, and added your function. i called the function without an echo and it worked fine. could you post some of the structure relating to those inputs and anything populating them?

edit: by inputs i mean live_invites, live_accepts, and live_ratio

  • 0

Odd, I've just done what you've just done and uploaded only what was necessary and it still doesn't work:

<html>
<head>
<script>
// Check that the invites, accepts, and ratio spans have loaded
while(!document.getElementById("live_invites").innerHTML || !document.getElementById("live_accepts").innerHTML || !document.getElementById("live_ratio").innerHTML)
{
	//alert('fg');
	document.getElementById("live_ratio").innerHTML = (Math.round(document.getElementById("live_invites").innerHTML / document.getElementById("live_accepts").innerHTML * 100) / 100).toFixed(2);
}
</script>
</head>
<body>
<span id="live_invites">245</span>:<span id="live_accepts">24</span> = 1:<span id="live_ratio"></span>
</body>
</html>

  • 0

That's because when you use it in the HEAD, the document hasn't been fully created yet. As a result, document.getElementById('ANYTHING') is pretty much guaranteed to fail. If you wrap it in a function and call it onload, it should work better:

<html>
  <head>
	<script>
	  function foo ()
	  {
		// Check that the invites, accepts, and ratio spans have
		// loaded
		while (!document.getElementById("live_invites").innerHTML
			  || !document.getElementById("live_accepts").innerHTML
			  || !document.getElementById("live_ratio").innerHTML)
		  {
			//alert('fg');
			document.getElementById("live_ratio").innerHTML =
			  (Math.round(document.getElementById("live_invites").innerHTML
						  / document.getElementById("live_accepts").innerHTML
						  * 100) / 100).toFixed(2);
		  }
	  }
	</script>
  </head>
  <body onload="foo()">
	<span id="live_invites">245</span>:<span id="live_accepts">24</span> =
	1:<span id="live_ratio"></span>
  </body>
</html>

  • 0

Adding to that, JavaScript runs in a separate thread so if you have an alert() call first in your while-loop, it'll probably have enough time to first render the document and populate the DOM object. That's why the line beneath it gets called a little later and gets executed properly since only then the document object is valid.

So a good lesson here: use the onload event to trigger something as soon as the page is loaded. Or if you want to do it even better, use the Prototype JS framework and observe the "dom:loaded" event! :p

  • 0

Thanks for all of your help everyone, it is really appreciated! :D

Ok it is now working great in my application, but it occassionally comes up with 'Infinity' or 'NaN' (presumably if AJAX hasn't populated the spans yet). I've managed to catch them, but for some reason I can't get it to re-call the function. It re-calls the function if I put an alert in, but again, doesn't if I don't.

This is the code I have:

// Calculate invite:accept LiveChat ratio
function live_ratio()
{
	document.getElementById("live_ratio").innerHTML = (Math.round(document.getElementById("live_invites").innerHTML / document.getElementById("live_accepts").innerHTML * 100) / 100).toFixed(2);
	while(document.getElementById("live_ratio").innerHTML == "Infinity" || document.getElementById("live_ratio").innerHTML == "NaN")
	{
		//alert('invoked');
		live_ratio();
	}
}

  • 0

No I'm not using any frameworks and would rather not implement one just to acheive this. I now have the following code:

// Calculate invite:accept LiveChat ratio
function live_ratio()
{

	//alert('invoked');

	if(document.getElementById("live_invites").innerHTML && document.getElementById("live_accepts").innerHTML)
	{
		document.getElementById("live_ratio").innerHTML = 'loaded';
	}
	else
	{
		live_ratio();
	}
}

It is refusing to call itself if the spans don't have content loaded yet. It just keeps live_ratio blank. However, if I uncomment the alert() line, it works. Why on Earth isn't the code above working?

I have ?6.08 in my PayPal account to anyone who can get it working:pp

Edit:> I've managed to get it working (fingers crossed), changed live_ratio(); to setTimeout("live_ratio()", 1); (taken from http://javascript.about.com/library/blrecursive.htm). Seems to be working, just double checking now.:DD

Edited by -Alex-
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.