Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

zlinuk

macrumors regular
Original poster
Jul 8, 2008
111
27
UK
Can a function make a call to itself? ie in theory would something like this work.

Code:
function checkForNull ()
           
          var i=document.getElementById("someElement").value;

         if (i=='null')
         {
         checkForNull ();
         }
         else
         {
         callDifferentFunction ();
        }

The idea is that onLoad the if statement will loop until the data (from an XML file) get loaded into "someElement".

Thanks in advance.
 
Can a function make a call to itself? ie in theory would something like this work.

Code:
function checkForNull ()
           
          var i=document.getElementById("someElement").value;

         if (i=='null')
         {
         checkForNull ();
         }
         else
         {
         callDifferentFunction ();
        }

The idea is that onLoad the if statement will loop until the data (from an XML file) get loaded into "someElement".

Thanks in advance.

Yes, this method of programming is known as recursion, where you call a method within that method itself.

.You can use the setTimeout function to put the program to sleep for a few seconds, rather then constantly calling the method, which may cause the page to slow down.
 
Thanks very much CM, oddly enough my original solution was this
Code:
function timing()
{
var t=setTimeout("callDifferentFunction()",500);
}

which worked ok when run locally but needs to be pushed out to something around 3 seconds when accessing over WAN.

To me it didn't seem a very elegant solution.

Would you recommend this as the better option. (you may notice that the code was shamelessly stolen from the W3Schools example)
 
Thanks very much CM, oddly enough my original solution was this
Code:
function timing()
{
var t=setTimeout("callDifferentFunction()",500);
}

which worked ok when run locally but needs to be pushed out to something around 3 seconds when accessing over WAN.

To me it didn't seem a very elegant solution.

Would you recommend this as the better option. (you may notice that the code was shamelessly stolen from the W3Schools example)

I would say that this

Code:
function timing()
{
var t=setTimeout("callDifferentFunction()",500);
}

is a far more elegant solution! :)

It is easier to read, and one of the most important rules of programming is not to redesign the wheel. You may as well use built in API methods such as setTimeout rather then spending time writing your own code for functionality that already exists.

If you need to push it out to three second, simply put 3000 as the second argument in the setTimeout function
Code:
{
var t=setTimeout("callDifferentFunction()",3000);
}

-Maw
 
If you explain more about what you're doing we can probably provide a better solution than to guessing how long it will take for something to load. You can make use of the onload event for other objects than just the document, and if you're loading XML you may be able to make use of some AJAX stuff.
 
Thanks for your input gents.

I am building a company intranet, the intention is that we can have quick and efficient access to both the technical and pricing information from a single source (this info is currently held on 2 seperate systems), there are approximately 600 products each of which will have a number of configurable options.

The backend is an access database (which in turn calls data from our accounting software, where the product pricing information is held).

I am using Dreamweaver as my editor of choice and I utilise Adobe's Spry Framework for menu's, animation, data handling, etc. All product information comes into the page as a Spry XML Dataset.

In this particular instance I am only working on a test page so that a principle can be established, this is what I am trying to achieve;

Product_A is made up of 2 seperate components;

Component_1 has 5 options (call this ds1)
Component_2 has 5 options (call this ds2)

So Selling Price of Product_A = selection from ds1 + selection from ds2

The two datasets are presented in seperate tables, each with selectable rows and a seperate detail region that contains the price for the selected component. The price detail region updates when a different component is selected in the table.

The task here was to simply add together the 2 prices and have the total presented as a "Total Price"

So this is what was needed.

When page initially loads carry out the calculation based on the default selection in the two tables.

When a different selection is made in either of the tables (and the price in the detail region changes) carry out the calculation again.

This solution works:

MyScripts.js

Code:
function DelayedStartCalc(){
	var t1=setTimeout("StartCalc()",3000);
  	var t2=setTimeout("StopCalc()",3500);
}

function DelayedStopCalc(){
  	var t2=setTimeout("StopCalc()",300);
}

function StartCalc(){
  interval = setInterval("Calc()",1);
}

function StopCalc(){
  clearInterval(interval);
  alert ("Stopped"); //This is here for testing purposes only
}

function Calc(){
  one = document.autoSumForm.firstBox.value;
  two = document.autoSumForm.secondBox.value; 
  three = (one * 1) + (two * 1);
  document.autoSumForm.thirdBox.value = three.toFixed(2);
}

On the <body>

Code:
     <body onload="DelayedStartCalc()">

On the <tbody> of both tables

Code:
      <tbody spry:repeat="ds1" spry:choose="choose" onmousedown="StartCalc()" onmouseup="DelayedStopCalc()">

The detail region

Code:
<form  name="autoSumForm">
<div spry:detailregion="ds1"><input  class="alignright" readonly="readonly"  type=text name="firstBox" value="{Price}.00"></div>
<div spry:detailregion="ds2"><input class="alignright" readonly="readonly" type=text name="secondBox" value="{Price}.00" /></div>  
<input class="alignright" readonly="readonly" type=text name="thirdBox" />
</form>

I would appreciate it if any of you .js guru's can suggest any improvement.
 
At the start of the thread you mentioned waiting for some XML data to be finished loading, but I don't see anything here about that. How is that XML being loaded in?

Here's some improvement on your Calc function though that can handle errors more gracefully.
PHP:
function Calc(){
  try {
    var one = parseFloat(document.autoSumForm.firstBox.value);
    var two = parseFloat(document.autoSumForm.secondBox.value);
    var three = one + two;
    document.autoSumForm.thirdBox.value = three.toFixed(2);
  }
  catch (e) {
    // Likely one of the values is not a number
  }
}
 
Thanks for that angelwatt,

re the XML, in the head of the document

Code:
<script type="text/javascript">
var ds1 = new Spry.Data.XMLDataSet("/Asp/SinglePinBracket.asp", "export/row");
ds1.setColumnType("Price", "number");
var ds2 = new Spry.Data.XMLDataSet("/Asp/2PinBracket.asp", "export/row");
ds2.setColumnType("Price", "number");
var ds3 = new Spry.Data.XMLDataSet("/Asp/DummyPins.asp", "export/row");
ds3.setColumnType("Price", "number");
</script>

which is then used as described above.

A couple of questions re your code:

what does the 10 represent at the end of the var declaration?
and
is catch (e) the same as catch (err)

Thanks
 
what does the 10 represent at the end of the var declaration?
and
is catch (e) the same as catch (err)

Thanks

I'll have to look into those Spry functions. I don't use DreamWeaver.

The 10 represents the base of the number being parsed. This makes sure it's base 10 and not base 16, 8, or binary. For instance, if it tried to parse 08 you would get 0 as the result and not 8 because base 8 numbers start with a 0 often. Though, I forgot the second argument is only used with parseInt and not parseFloat so you can remove that from the code I provided.

You can use "e" or "err" or any variable name really for the catch. It just holds the error message from the try block when it fails. You can do whatever you want with the error message including nothing.
 
Alright, I found a decent page on Spry from Adobe. There is a onDataChanged event you can use to call another function, which is what you want. Here's example code they offer. The linked page is long so search for "onDataChanged" to find it more easily.

PHP:
var dsPhotos = new Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo");
...
var myObserver = new Object;
myObserver.onDataChanged = function(dataSet, data)
{
	alert("onDataChanged called!");
};
dsPhotos.addObserver(myObserver);
So, if I understand it, you can then change your code to something like,
PHP:
function Calc() {
  try {
    var one = parseFloat(document.autoSumForm.firstBox.value);
    var two = parseFloat(document.autoSumForm.secondBox.value);
    var three = one + two;
    document.autoSumForm.thirdBox.value = three.toFixed(2);
  }
  catch (e) {
    // Likely one of the values is not a number
  }
}
var theObserver = new Object;
theObserver.onDataChanged = function (dataSet, data) { Calc(); };

var ds1 = new Spry.Data.XMLDataSet("/Asp/SinglePinBracket.asp", "export/row");
ds1.setColumnType("Price", "number");
ds1.addObserver(theObserver);

var ds2 = new Spry.Data.XMLDataSet("/Asp/2PinBracket.asp", "export/row");
ds2.setColumnType("Price", "number");
ds2.addObserver(theObserver);

var ds3 = new Spry.Data.XMLDataSet("/Asp/DummyPins.asp", "export/row");
ds3.setColumnType("Price", "number");
ds3.addObserver(theObserver);
Then you shouldn't need to worry about using the onload event on the body tag. I can't test this code since I don't have DW, so it may not work as is, but should put you in the right direction.
 
angelwatt, thanks again for your efforts, I will have a read up on observers and implement you modifications when I get into the office in the morning.

The test page is evolving nicely, i've now dropped the use of <form> and <input> in favour of a simple <table> and the use of .innerHTML to read/write to the target <td>
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.