Getting Loopy – Nested Javascript Loops

May 26th, 2006

Complex loops with Javascript can get tricky. Double-nested loops, dynamic field names, and all kinds of other things can leave a programmers head spinning. Let’s get Loopy and tackle this in a nice programatical manner.

Recently presented with a form similar to a questionaire, there were a bunch of questions, each with the possibility of multiple answer options and a comment box. To make matters worse, I needed to check if there were comments entered when a certain option was selected. Rather than go through one by one and create a huge function, I tapped into the power of loops, and the power of dynamic form element naming.

Let’s say our form is a questionaire with radio buttons for options and a comment box. The form would look something like this:


<div>
  <form id="frmdefault" onsubmit="validateForm();" method="post" action="results.php">
    <table>  
      <tr>
        <td>Q1</td>
        <td><strong>How good are you at javascript?</strong></td>
        <td><input type="radio" id="q1" name="q1" value="Great" />Great!</td>
        <td><input type="radio" id="q1" name="q1" value="Average" />Average</td>
        <td><input type="radio" id="q1" name="q1" value="Bad" />Bad</td>
        <td><input type="radio" id="q1" name="q1" value="NA" />N/A</td>  
        <td><textarea id="q1_comments" name="q1_comments" rows="2" cols="5"></textarea></td>
      </tr>
      <tr>
        <td>Q2</td>
        <td><strong>How do you think this tutorial rates?</strong></td>
        <td><input type="radio" id="q2" name="q2" value="Great" />Great!</td>
        <td><input type="radio" id="q2" name="q2" value="Average" />Average</td>
        <td><input type="radio" id="q2" name="q2" value="Bad" />Bad</td>
        <td><input type="radio" id="q2" name="q2" value="NA" />N/A</td>  
        <td><textarea id="q2_comments" name="q2_comments" rows="2" cols="5"></textarea></td>
      </tr>
      <tr>
        <td colspan="7"><input type="submit" value="Validate Form" /></td>
      </tr>
    </table>
  </form>
</div>

This makes our nice little form. Of course, you can make it into nice table-less layout and all that, but that is beyond the scope of this article, so I used a table.

Let’s say that we want to:

  1. Make sure a radio option is selected for each question
  2. require a comment to be entered in the textarea if “Bad” is selected

In order to do this, we need to first loop through our radio buttons to see if one is selected. If “bad” is selected, prompt for comments to be entered. Finally, we need to loop and repeat the above for every question.

In less than 30 lines of (well-formatted) code, we can set up a double-looping function that does all of this, will work for an infinite amount of questions or possible answers (except a single answer- but, you shouldn’t be using radio buttons for a single element choice anyway). I will explain the code below the function:


<script type="text/javascript">

function validateForm() {
  var theform = document.getElementById("frmdefault");

  for (i=1; i&lt;3; i++)
  {
    for (j=0; j<theform .elements["q"+i].length; j++)
    {
      if (theform.elements["q"+i][j].checked)
      {
        if (theform.elements["q"+i][j].value == "Bad")
        {
          if(theform.elements["q"+i+"_comments"].value == "")
          {
            alert("Comments required for Q"+i+" when Bad is selected");
            theform.elements["q"+i+"_comments"].focus();
            return false;
          }
        }
      }
      else
      {
        alert("Please select an option");
        return false;
      }
    }
  }
}
</script>
</theform></script>

It looks very complex and tricky, but as we go through it you will see it makes a lot of sense. The outer loop is set for the number of questions we have. In this case, we have 2. You could port this a step further an make this number count dynamic as well. (In most cases though, I feel as if that’s an un-necessary step as most polls or scripts like this won’t change once made. If you are running some kind of dynamic form generator, then yes, another step will need to be added to find how many questions there are. Basically, you’d have to add another loop around all of the above that counts how many questions there are.)

Notice, we start with i=1 instead of the common i=0. This is because our questionaire starts with question 1, not question 0. It makes things easier to address in the inner functions. Because of this, we also must up our incremented variable to i<3 instead of i<2, because of the increased initialized variable. Another option would be to use i< =2, thus allowing for it to be equal to the max index.

The outer loop, i, will call the inner loop j, i times. Inside the inner loop, we need to dynamically address how many radio buttons there are. The length function figures this out for us and begins our data check to ensure at least one element is checked per our requirements. Note that we are using ["q"+i]. This evaluates to our question number based off the outer loop. If the element array does not have one checked, it will return false and prompt the user to select one. If there is an element checked, it will then look and see if that checked value = “Bad”. If it is, it then checks to see if there is anything in the textarea field for comments. If not, we return home free and we return to the outer loop for testing the question count to see if we need to do this all over again for the next question, if one exists. When all is passed, the form will submit to the target in the action attribute of the form tag, in our example, results.php.

Of course, this all depends on Javascript being enabled, and in a browser than supports the getElementById() functionality. Thus, it is important to also use server-side scripting to double check the submitted results. The Javascript just adds a friendly alert so that the whole page doesn’t need to be submitted every time an error occurs.

Have a better idea? I’m sure this code can be improved upon, and thus I’m curious to hear if anyone else has a similar function set up for this type of form checking. I appreciate your comments, as always.

Problematic SQL Sorting

May 25th, 2006

Sometimes, all you want to do is a simple ORDER BY, but it just doesn’t work. SQL has some quirks when trying to sort “text” numbers, especially when they are decimal numbers.

Consider the following Database table, myTable:


Code  varchar(5)  | Descr varchar(100)
------------------|--------------------
1                 | Code 1
1.1               | Code 1 point 1
1.2               | Code 1 point 2
2                 | Code 2
3                 | Code 3
10                | Code 10
11                | Code 11
20                | Code 20

If you wanted to do a simply query to order by the Code field, one would think that a simple ORDER BY would do the trick.


SELECT 
   Code
  ,Descr
FROM
   myTable
ORDER BY
   Code ASC

Unfortunately, it doesn’t. This produces:


Code              | Descr           
------------------|--------------------
1                 | Code 1
1.1               | Code 1 point 1
1.2               | Code 1 point 2
10                | Code 10
11                | Code 11
2                 | Code 2
20                | Code 20
3                 | Code 3

In order for the DBMS to interpret the Code field as a Number, not as text, we need to CAST it to a numeric datatype, in this case i will use float.


SELECT 
   cast(Code as float) AS 'Code'
  ,Descr
FROM
   myTable
ORDER BY
   Code ASC

Yup, this doesn’t work either. Suddenly you may find yourself with 1.999999999999 instead of your code 2. The rounding mechanism is not perfect. So, we need to take this a step further, and once again re-cast our float as a varchar. This will fix the rounding problem.


SELECT 
   cast(cast(Code as float)as varchar) AS 'Code'
  ,Descr
FROM
   myTable
ORDER BY
   Code ASC

The above will produce your results table nice and neat and perfectly sorted.


Code              | Descr
------------------|--------------------
1                 | Code 1
1.1               | Code 1 point 1
1.2               | Code 1 point 2
2                 | Code 2
3                 | Code 3
10                | Code 10
11                | Code 11
20                | Code 20

Knowing how to work around the tweaks of any system will save you a lot of time and hair pulling. Fortunately, there are built in functions that make it easy on us developers, but sometimes finding them can be a little tricky.

This is the first of my SQL articles to come, so check back often for new articles and updates.

This code was tested for MSSQL Server 2000. Rounding quirks may react differently in your DBMS.

Like this article? Please Digg it

Is it Time to Abandon 800×600?

May 16th, 2006

Yesterday, May 15th 2006, Yahoo! Inc. released a link in their blog to a preview page of their new layout which perhaps may set the standard in pushing away from developing for 800×600 resolution. It will not fit without horizontal scrollbars at 800×600 resolution, but fits the screen nice and neatly with just a small padding around the edges in 1024×768. Frankly, I’m suprised to see them make the move to a fixed-width, non-fluid template.

The new left navigation menu is also very cutting edge “web 2.0″. While still sorted in alphabetical order, it utilizes web 2.0-style “tags” in which the more popular items are in a larger font.

Will this release finally give the last push to totally abandon 800×600? I don’t know if i’m quite ready for that yet. I for one know that both my parents in their early 50′s use 800×600 on their 17″ CRT, and they have a hard time seeing that sometimes, so I cannot imagine them moving to 1024×768. Perhaps, this will become the leading accesibility issue, perhaps it will have no effect. But I for one still believe in making sites fluid, or at the very least, not so wide as too force a horizontal scroll bar.


EDIT: 5/17/2006, 14:36 GMT -5

I think it is fitting that after nearly 20,000 views and 1500+ Digg’s to this page, that i include the real-time image of the resolution stats visiting this page. While only 2% as of this writing are on 800×600, the results are skewed as us techies are more apt to have better equipment.

Pie Chart for Resolutions

Microsoft.com Goes Valid

May 5th, 2006

Hell must have frozen over sometime in the past month or so. With the newest rendition of the Microsoft.com Home Page, the markup actually passes W3 validation for HTML 4.01 transitional. Further noteworthy, is that there are accessibility features in place, such as “Skip to main content” links for CSS disabled browsers.

Unfortunately, there are still a couple dozen CSS errors and there are still a bunch of IE-only filter tags present. Not to mention, the javascript-required flyout menus and hidden div’s that appear onmouseover, or the in-line style attributes. Then, there’s the image maps, the iframes, the inconsistancy of single and double quotes around attributes, camel-case classes and id’s, nested tables, nested tables holding divs that hold lists that don’t even need to be in a table or div at all, and…….

I think you get the point.

While it’s great to see the anti-w3 gods themselves actually produce valid HTML, there’s a still a lot of poorly written code that needs to be addressed. Perhaps the markup was the first step. We shall only wait and see what the next rendition produces.

This gets me thinking though: Perhaps they viewed their site with their new IE7 beta and realized that their site needed to be fixed in order to not fall apart in their new software offering. Or, are we seeing a new side of the company?

vBulletin VS. Invision Power Board

April 28th, 2006

This is quite possibly one of the biggest debates in the pre-sale sections of both official sites, vBulletin.com and invisionboard.com. Before choosing a software, potential customers want to hear from people who use it. The biggest problem is asking which one is better on the respective sites, is like asking the CEO of Coca Cola if he thinks Pepsi is better than Coke.

I have been a long-time IPB user, hosting over 4 large and successful forums on the software. For my latest endeavor, I decided to give vBulletin a try. With that site nearly all set up and nearly ready for its June 1st launch, it’s time for a no holds-barred head to head opinion of the two softwares. This comparison is my point of view after using both latest software releases as of this writing: 2.1.5 for IPB, and 3.5.4 for vB.
Read the rest of this entry »

Classic ASP and AJAX

March 29th, 2006

There aren’t many tutorials on the web for Classic ASP and AJAX interfaces. Classic ASP is just about fazed out at most companies, but there are still plenty of legacy applications that use it. There is a lot of confusion about AJAX and what it is. Mainly, it is a client-side application that sends data to a back end parser, and thus the back-end processor can be written is anything from asp to cfm to php to old-school perl cgi’s.
Read the rest of this entry »