Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: can you place an if statement in a for conditional?

  1. #1
    Join Date
    Apr 2009
    Location
    Sydney, Australia
    Posts
    118
    Thanks
    16
    Thanked 1 Time in 1 Post

    Default can you place an if statement in a for conditional?

    Hi, my latest attempt with JavaScript is to take a couple of variables in the innerHTML of page spans to tally a total value.

    I use an event handler in the body

    Code:
    			<select id="retreat1" onchange="tallyTotals(this)">
    			<option value="selected"></option>
    			<option value="value1">1</option>
    			<option value="value2">2</option>	
    			</select>
    to call a script similar to this... so far.

    Code:
    function tallyTotals()	{
    for(var i=1;if(document.getElementById('retreat'+[i]));i++)	
    	{
    	alert("Hello");
    	}
    }
    There are several select tags in the form with values I would like tallied and shown in an innerHTML. I know there are probably better methods I will be shown by this article, and by all means I would like to learn.

    But my instincts tell me there is a syntactical method which will allow any argument inside the parameters for the for loop.

  2. #2
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    I don't see any logical reason that would not work (with one important change*), but that is really a bad idea:
    that will continuously generate "hello" (repeatedly), until something changes-- if you are repeating the alert, then nothing can change-- it will get stuck forever.

    A for loop is somewhat useless, in the sense that it is the same as while:
    Code:
     for (statement 1; statement 2; statement 3;) {
    ...
    }
    
    //same as
    
    statement 2;
    while (statement 1) {
    ...
    statement 3;
    }
    So in this sense there is no reason you could not just use a while loop instead-- a for loop is just a specific complex version of a while loop, and that should work also.


    *The only real problem is that you are basically using "if" twice:
    Again, let's simplify the problem to a while loop:
    while (condition)
    Means "continue doing this if (condition) is true"
    while (if(condition))
    Means "continue doing this if (if(condition)) is true"

    Because of this, you do not need the "if" at all-- just what you would put INSIDE the if, now inside the for loop:
    for(var i=1;document.getElementById('retreat'+[i]);i++)


    technically, I suppose that may not harm anything, but it is a weird way to code--
    the inside if will return true or false, then:
    if (true) => true
    if (false) => false
    So, really, there is no harm, but it is certainly not needed.



    Anyway, as for the idea overall, the best way to approach it is probably entirely different: use events or perhaps a silent loop that looks for this condition and acts on it, instead of using the sort of loop above.
    1. Try something like body.onclick = dosomething();
    or
    2. while() { ///empty condition: always true, or you could use while(true)
    if (condition) { dosomething(); }
    }
    That would loop forever waiting until 'condition' is true, and then dosomething().
    Daniel - Freelance Web Design | <?php?> | <html>| español | Deutsch | italiano | português | català | un peu de français | some knowledge of several other languages: I can sometimes help translate here on DD | Linguistics Forum

  3. #3
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Code:
    function tallyTotals(){
    for(var i = 1; document.getElementById('retreat' + i); ++i){
    	alert("Hello");
    	}
    }
    I don't know about the if. The above will work. It will continue to loop until there are no more document.getElementById('retreat' + i) elements'.

    For loops are better than while loops if there's a lot of looping going on, more efficient.

    Generally though, aside from the syntax, it makes no difference. However, unless you know for an absolute fact that your code will never have many loops, for is better.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  4. The Following User Says Thank You to jscheuer1 For This Useful Post:

    sniperman (01-12-2010)

  5. #4
    Join Date
    Apr 2009
    Location
    Sydney, Australia
    Posts
    118
    Thanks
    16
    Thanked 1 Time in 1 Post

    Default

    First off, thank you very much for both your contributions. I knew it was a weird way to code but I wanted to eliminate some redundant looping and reduce the loop rate to the actual elements, which would in turn build an array.

    The original function went something like this.

    Code:
    var tagsarray = new Array();
    
    function defineTotal()	{
    
      for(var i=1;document.getElementById('retreat' + i);i++) // count all instances of the select form field
    	{
    	if (document.getElementById('retreat'+[i]))	{
    	tagsarray.push(document.getElementById('retreat'+[i])) // list all instances in an array
    												}
    	}
      alert(tagsarray[0].options[tagsarray[0].selectedIndex].value);
    }

    I suppose the conventional way to do this is written below and I eventually used this.
    Code:
    var tagsarray = new Array();
    
    function defineTotal()	{
    tag = document.getElementsByTagName('select');
    
      for(var i=0;i<tag.length;i++) // count all instances of the select form field
    	{
    	if (document.getElementById('retreat'+[i]))	{
    	tagsarray.push(document.getElementById('retreat'+[i])) // list all instances in an array
    												}
    	}
      alert(tagsarray[0].options[tagsarray[0].selectedIndex].value;
    }
    But, after I came back to this forum and read the posts, I removed the if statement from the for loop's statements (otherwise I guess I would have created a subroutine). And I reverted from the conventional way to my original way because it removed the need to cycle through with getElementsByTagName().

    The point of the exercise, in my mind, was to loop only through direct instances of the tag controlled by an incremental id (i.e. retreat1, retreat2).

    I know it's clunky, and I am now having trouble looking for a good way to obtain the value of the selected index and to use this value in some eCommerce kind of fashion to calculate a total.

  6. #5
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    There are various ways to make something like this more efficient. I'm not really clear as to using the getElementsByTagName() being more efficient than sequential calls to getElementById(). It depends on the document. The byTagName method can target elements that are children of another element, thus narrowing down the scope of the node list, while byId cannot. A single use of byId is faster, but not multiple ones. I'm not clear on how many it would take to be slower than byTagName, probably not too many. With byTagName your code could more easily apply to multiple forms on one page, giving results for each individual form. There are also document.getElementsByName() and the form's elements collection, either of which can be a better choice, depending upon the situation.

    Getting back to the for loop, these are most efficient when as many variables as possible are defined ahead of time, and those that cannot be are at least declared. Also, incrementing/decrementing - as long as it's still logically valid - is more efficient as what they call pre, as opposed to post. With pre, the two plus or minus signs come before the variable, with post, after. The meaning is slightly different, but often interchangeable, or adaptable. With pre the variable's value changes in the instant in which it is done, with post it doesn't change until the next instance of the variable is accessed. Because of this post must remember, pre doesn't and so is more efficient.

    Here are these principles used in something like I think you are doing:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script type="text/javascript">
    function defineTotal(){
    	var tot = 0, i = 1, el;
    	for(i; (el = document.getElementById('retreat' + i)); ++i){ // loop all sequential instances of select's with an id of retreat#
    		tot += +el.value; // add their value to tot
    	}
    	alert(tot);
    	return false;
    }
    onload = function(){
    	document.forms.totform.onsubmit = defineTotal;
    }
    </script>
    </head>
    <body>
    <form name="totform" action="#">
    <div>
    <select id="retreat1">
    <option value="0">0</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    </select>
    <select id="retreat2">
    <option value="0">0</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    </select>
    <input type="submit" value="Total">
    </div>
    </form>
    </body>
    </html>
    I chose byId because with just two lookups it's probably faster.

    One big problem here is that it expects a lot from the markup. If things change, it may no longer be efficient and/or even work. Some markup dependency is inevitable. It should be kept to a minimum though.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  7. The Following User Says Thank You to jscheuer1 For This Useful Post:

    sniperman (01-13-2010)

  8. #6
    Join Date
    Apr 2009
    Location
    Sydney, Australia
    Posts
    118
    Thanks
    16
    Thanked 1 Time in 1 Post

    Default

    The initial build I am attempting to code will have an internal panel to input dynamic variables for the form, kind of a pseudo CMS before I decide whether it is worthwhile to store the data on a server database and use JavaScript DOM/AJAX to retrieve them.

    Currently this is out of my immediate scope. And thanks for highlighting markup dependency. I am seeking to make the form as automated as possible with only placeholder and IDs for variables that will change the markup. So markup dependency will cause me to rethink the approach because the html on the page will not be static.

    In regards to the code, I spent 10 hours to engineer a solution. I don't mean to step on any toes but by using the second statement in your code

    Code:
    for(i; (el = document.getElementById('retreat' + i)); ++i)
    doesn't that mean the statement is assigning whatever 'retreat'+i is, and if that is the case, the for loop will always return true because even if it returns NaN or empty it is being assigned to el? Whereas with my version I only want to check whether the ID instance exists, and if so, perform the desired functions.

    This is my functional code for now... although the problem to handle now is that each for loop appends new instances of the same objects into the tagsarray Array. I am thinking I should place the array inside the for loop so it always overwrites the information.

    And of course, I now have to work on a new function to minus the value once the option is deselected... coding!!

    Code:
    var tagsarray = new Array();
    TotalPrice = 0; // the default value inside the Total Price box
    
    function tallyTotals(fld)	{
      for(var i=0;document.getElementById('retreat'+i);i++) // count all instances of the select form field if its ID exists, 
    	{
    	if (document.getElementById('retreat'+[i]))	
    		{
    		tagsarray.push(document.getElementById('retreat'+[i])) // list all instances in an array
    		}
    	}
    	for (var i=0;i<tagsarray.length;i++)
    		{
    
    		if(document.getElementById(fld.name).name==tagsarray[i].name) // if the name is equal to the name in tagsarray
    		  { 
    		  var retreat_price = document.getElementById('price'+[i]).innerHTML; // retrieves the associated price from span innerHTML and stores in a variable
    		  retreat_price = retreat_price*tagsarray[i].options[tagsarray[i].selectedIndex].innerHTML; // returns the innerHTML value of the option chosen to retreat_price variable
    		  TotalPrice+=retreat_price; // stores new retreat price into the total
    		  document.getElementById('total').value = TotalPrice; // also returns this total to the page
    		  }
    }	  
    
    		
    		}

  9. #7
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    As for:

    Code:
    for(i; (el = document.getElementById('retreat' + i)); ++i)
    Notice the red parentheses. They mean evaluate this expression first. The fact of, say:

    Code:
    el = false;
    really doesn't have any boolean value anyway, at least not due to the = sign which is an assignment operator, not a comparison operator. That line's value is the value of the result of the assignment, the value of el, false in this case.

    You can test all that by putting an alert inside the loop for my code, it will fire only twice.

    On to your code, and I will have a closer look at it later. The array, if required at all, could be defined within the function. So could possibly the total. It is more efficient to use the literal array syntax:

    Code:
    function tallyTotals(fld)	{
    var tagsarray = [];
    TotalPrice = 0; // the default value inside the Total Price box
      for(var i=0;document.getElementById('retrea . . .
    Now, I've not really looked this over in detail yet. But by defining the array in the function, it will be reset each time the function runs, so will not accumulate duplicate entries, though it will not be available outside the scope of the function unless something is done to make it so, though that may not be required. Setting the total inside the function has a similar effect, and may eliminate the need for any subtraction. Each time the function is run it will only include those values that are selected, skipping any that have become deselected.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  10. #8
    Join Date
    Apr 2009
    Location
    Sydney, Australia
    Posts
    118
    Thanks
    16
    Thanked 1 Time in 1 Post

    Default

    Is it true that all conditionals inside a for loop have to return boolean, i.e. TRUE or FALSE.

    From what I can see

    {

    i exists so it's true
    (el = document.getElementById('retreat' + i)) exists and returns true to el
    ++i is true because i exists and can be added to

    }

    so even if you ran a subroutine with calls to other functions and set this subroutine as a condition of a for loop, as so

    Code:
    for (condition1; if (new conditions) {runexternalfunction(eval)};++i;)
    In theory, that should work. Although I don't know how practical that would be.

  11. #9
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Only thing for that would be to try it out. However:

    Code:
    if (new conditions) {runexternalfunction(eval)}
    might have the return value of:

    Code:
    runexternalfunction(eval)
    not of:

    Code:
    (new conditions)
    If (new conditions) were false, there could very well be an error, as perhaps at that point nothing to evaluate on a boolean basis would be presented to the script parser. Even if it all worked in theory, the syntax might need to be beefed up a bit.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  12. #10
    Join Date
    Apr 2009
    Location
    Sydney, Australia
    Posts
    118
    Thanks
    16
    Thanked 1 Time in 1 Post

    Default

    I might keep that one in my back pocket and run some tests at a later date. It would be interesting to see a for loop with embedded functions run a form validator sequence for example, or to be an initALL() for DOM like Firebug for Firefox.

    A for loop as a master control for subroutines sounds cool. Would have to be beefed up a bit though!

    Thanks for all the input.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •