• 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.
  • Posts

    • "...but it may not be Microsoft's fault" seems like a reasonable way to tease what is going on without leaving the user with a false impression that an update is the problem. A title isn't a summery, it is meant to entice the user to read the article. It should not contain a misleading premise; which this title does not. You could maybe complain that the first paragraph should have included that detail. The writing style popularized over 100 years ago in newspapers will cover the most important information as soon as possible with details and nuance added later; the idea being that with each new paragraph you have less of the reader's focus.
    • Samsung Galaxy XR arrives in the UK with new AI and enterprise features by Fiza Ali Samsung is bringing its Galaxy XR headset to the UK several months after the device made its debut as the first headset built on Google's Android XR platform. The headset was first teased in late 2024 alongside Google's introduction of Android XR before making its commercial debut in 2025. Developed in collaboration with Google and Qualcomm, Galaxy XR combines mixed reality experiences with Gemini-powered AI features, allowing users to interact with digital content using voice, gestures, and visual inputs. While the hardware itself remains largely unchanged from the version Samsung unveiled last year, the company is using the UK launch to spotlight several software enhancements that have arrived through recent updates. Among the most notable additions is deeper integration with Google's ecosystem. Galaxy XR users can explore destinations through Google Maps' Immersive View, receiving AI-powered recommendations and contextual information from Gemini while navigating virtual environments. Furthermore, entertainment experiences have also expanded; users can watch 180-degree and 360-degree videos on YouTube, browse spatial content converted into 3D, and ask Gemini questions about on-screen content without interrupting playback. Samsung is also highlighting mixed-reality features such as Circle to Search, which allows users to identify real-world objects through hand gestures while using the headset's video pass-through mode. Another feature automatically converts photos and videos into spatial 3D experiences. Moreover, the headset now also supports Android Enterprise, allowing organisations to manage deployments using existing Android management tools. Annika Bizon, Vice President, Product and Marketing, Mobile Experience, Samsung UK & Ireland, talked about the device, stating: The headset is powered by Qualcomm's Snapdragon XR2+ Gen 2 platform and features dual 4K Micro-OLED displays. The tech giant says that users can expect up to 2.5 hours of battery life. Samsung also confirmed that Galaxy XR will continue receiving software and security updates as the company works alongside Google and Qualcomm to expand the Android XR ecosystem. Galaxy XR is now available for pre-order and will go on sale on 8 July. Customers interested in trying the headset before launch can visit Samsung KX in London and selected Samsung Experience Stores from 17 June. Finally, the company will also host a livestream on 19 June showcasing the headset's capabilities and answering questions from prospective customers.
  • Recent Achievements

    • First Post
      Jocimo earned a badge
      First Post
    • Week One Done
      suprememobiles48 earned a badge
      Week One Done
    • One Month Later
      Windows Guy earned a badge
      One Month Later
    • One Month Later
      Prasann earned a badge
      One Month Later
    • Week One Done
      Prasann earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      521
    2. 2
      +Edouard
      174
    3. 3
      PsYcHoKiLLa
      95
    4. 4
      Steven P.
      84
    5. 5
      ATLien_0
      70
  • Tell a friend

    Love Neowin? Tell a friend!