Q&A Selecting in a Listbox after submit

February 4th, 2008

This question was submitted on February 4th, 2008:

Hi,
I have a combo box called "A" which contains fruits and vegetables
and a list box called Types(i.e) which will display the corresponding types(Eg if we select Fruits then it will display apple, mango and if we select vegetable then it will display carrot, onion etc.
Based upon the selection in the list box and on clicking submit button it will populate the table which will containe prices.
On First loading the page both the combo box and list box will contain "select" as first option. Then we choose Fruits and their corresponding types listed in the List box and based on the selection in the list box and after clicking submit button the table gets populated. All the values are updated in the database.
On Reloading the page we should get the same value which we have selected in Combo Box "A" and list box "Types" and table also should be populated. I am getting the List box value from the database and i am iterating with the list of values in List box.
Eg If i selected Mango and then clicked submit button and same is updated in database.So while i am reloading the
page i am comparing mango with apple, pineapple, mango,custard apple etc. If a match is found i am highlighting that value and the corresponding table should be displayed
The problem here is combo box value and list box value is first displayed and then it takes few seconds to display the Table which looks very awkward for the end user.
Below is the coding which i have done....

JavaScript:
  1. for(optionId=0, key=1, value=0; optionId <maxEntityCount; optionId++){
  2.  document.form1.listbox.options[optionId] = new Option(fruitsArray[key],fruitsArray[value]);
  3.   if(typesoffruits == fruitsArray[key])[html]
  4.   {
  5.     document.form1.listbox.options[optionId].selected = true;
  6.     isSelected = true
  7.   }
  8.   value=value+2;
  9.   key=key+2;
  10. }
  11.  
  12. if(isSelected == true){
  13.   loadtable();
  14. }

I want to know whether there is any way in java script such that without iterating the loop i should able to highlight the value which i got from database and the corresponding table should be loaded. That is without iterating typesoffruits with fruitsArray i must able to highlight the typesoffruits and its table should be displayed.

Thanks for patiently reading such a long mail..
Thanks for your efforts and response.[/html]

What it sounds like you're looking for here is actually pretty simple to accomplish. You're keying on the key here, and if you've got the relationship set up the same way in the select element, you can very easily set them to be selected with the following code:

JavaScript:
  1. /*
  2.    if "mango" is selected, and has an id of 1, we assume
  3.    that the option in the list box is going to look like this:
  4.    <option value="1">Mango</option>
  5.   */
  6.   var elm = document.forms['form1']['listbox'];
  7.   elm.options[1].select = true;

Keep in mind, however, that in order for this to work, you must have the elements in the select element ordered by the key, and not alphabetically.

So you'd need to have:

HTML:
  1. <select name="listbox">
  2.   <option value="0">Select</option>
  3.   <option value="1">Mango</option>
  4.   etc...
  5. </select>

Without more information, that's the best answer I can provide. If you'd like to submit the code for review and adjustment, please feel free.

Comments always welcome!
Anthony

Followup 2/5/2008:

Thanks Anthony for you very valuable suggestion and help. That code is working fine. I am having one more query ...
How can i get the multiple selected values from lIst box using Java script.

Example: Consider i have mango, apple, grapes,strawberry in a listbox.
I am selecting apple and grapes and on click of submit button I am calling a javascript method called getFruits(). In that method, how can i get the selected values i.e(apple and grapes).

Thanks and Regards

This is fairly simple as well. Hat tip goes to DigitialAmit.com, where I picked up this nifty little snippet that does precisely what you need.

JavaScript:
  1. var arSelected = [];
  2.  
  3. function getMultiple(ob) {
  4.   while (ob.selectedIndex != -1) {
  5.     if (ob.selectedIndex != 0) {
  6.       arSelected.push(ob.options[ob.selectedIndex].value);
  7.     }
  8.      ob.options[ob.selectedIndex].selected = false;
  9.    } // You can use the arSelected array for further processing.
  10. }

Which will get all of the selected items and then deselect them. If you wanted to re-select them after you did the collection, you could simply loop through your arSelected array and set them to selected again.

All the best,
Anthony
price oem soft Wordpress Wordpress CMS

Adding Desktop Context Menu Entries in Vista

January 18th, 2008

I like to think of myself as something of a power user when it comes to Microsoft Operating Systems in general. I should be, after 25 years of messing around with every new version except Millenium. I don't think they'll ever live that one down out in Redmond, and I personally don't think they should be allowed to live it down, ever. Ugh.

But I like to tweak. It's in my nature. I had Vista for all of two hours when I disabled UAC, but that was a matter more of necessity than anything else. It wouldn't let me install Apache or muck around with my classpath, which was both buggy and irritating. Of course, once UAC was dead, Apache installed just fine, and the world was a happy place in Anthony-land.

A little background on this tip: I spend a lot of time on remote servers. I get used to the way things are typically set up and organized, and I want windows to behave itself appropriate to the environment that pays my bills. When you Putty into a server to change system level settings, recompile a PHP distro, whatever the case may be, you're not faced with the same command line syntax or directory structure ("folder structure", if you wanna be like that) that you see in Windows. In Windows, you see something like:

c:\Program Files\Apache Group\....

and in *nix, it's more like

/usr/sbin/.....

So when I want to get into the conf/ directory for a website on the server, the commands look like this:

cd /var/www/vhosts/domain_name/conf
vim httpd.conf

And by default, Apache on Windows installed the htdocs folder and configured me up to:

c:\program files\Apache Foundation\Apache....\htdocs

Which made me keep doing mental gymnastics and wondering where I was, since I run just about everything on the command line. I came up with a solution that is likely to irritate the sensibilities of some people, since it means editing the dreaded registry... da da dummmmmm

(This tutorial assumes you have admin privileges. If you like, you can turn UAC back on later.)

Seriously, before you do anything in this tutorial, do this:

CODE:
  1. hold down the windows key
  2. press "r"
  3. type "regedit"
  4. Click on "Computer" waaaay up top
  5. Click File->Export and follow the command prompts

NOT backing up your registry is just plain irresponsible.

Ok, so now, for my purposes, I wanted to add a new command line window in a certain folder to the context menu for the desktop. First thing is to open regedit, just like we did, or if you're still in there after the export I know you did because you're a smart and thoughtful person, so much the better. Everyone else, open up regedit.

The stuff we're going to mess around with is located in:

CODE:
  1. [HKEY_CLASSES_ROOT\Directory\Background\shell]

Right-click on shell and select New->Key
Name this key something small and simple, don't ad any spaces. I find relevance helps.
In the values side of the window, you see something similar to:

CODE:
  1. Name          Type          Data
  2. Default        REG_SZ      (value not set)

Double-click on default, and enter a name for the context menu item ("Server Root", in my case).
Click Ok

Ok, so it should look something like this about now:

CODE:
  1. Directory
  2.     Background
  3.       shell
  4.         cmd
  5.         your_key_name

Right click on your key name (If you entered "paint", then click "paint"), and click New->Key again.
This time, you have to name the key [i]command[/i]
In the values pane on the right hand side, enter the command you want to execute when you click the entry.

So if I want to open a command line with a green background and yellow text open in a new mysql session, I would enter:

cmd.exe /T:2e /K mysql -u root -pmypassword

Or any other valid windows command.

~A!

PHP Expert Editor (Ankord Development Group)

October 21st, 2007

Here at MPP, we're very big on supporting software companies who make great products that are reliable, trustworthy, and relatively free of bugs. When soemthing comes along that really makes us wince, though, we have to say something about it.

Such is the case with PHP Expert Editor, the PHP IDE from Ankord Development Group. It has very few features that the freeware Dev-PHP doesn't have, and it has a few things that the others don't.

  • Frequent Random Crashes - At least once a day, the application will simply stop working in the middle of typing a line of code. Repeated inquiries to support netted us zero replies.
  • Wonky laptop behavior - Our developers often use two or more monitors on their machines, and we're all on laptops. If we need to present to a group, we'll hook up to a projector. With PHP Expert Editor, disconnected or reconnecting an external monitor disables the ability to open a file or create new files until the application is restarted. This is exceedingly annoying.
  • Macros that simply don't work - There is a macro interface, but it's just an interface. Macros just don't work, no matter what you do.

Did I mention that it crashes randomly in the middle of writing code? Nothing like losing your work in all unsaved open files randomly and at the drop of a hat for seemingly no reason, definitely.
Normally, we don't complain about software too hard that we use from day to day. Then again, normally the software works.

Take it from a professional programming house, Ankord's PHP Expert Editor offering is a lemon, and their support has been abysmal in our experience. Forget purchasing it, get Dev-PHP instead. It has all the same features and doesn't lock up and die for no reason.

~A!

A Quick Note About header()

October 14th, 2007

I've seen a great many questions come in lately on the use of the header() function in PHP. This is just a quick note to describe it's use and some of the issues surrounding it.

There are two basic types of headers when we talk about HTTP Header directives. Request Headers and Response Headers. Request headers are what your browser sends to a server, and response headers are what the server sends back. I've seen more complicated explanations, and they are accurate, but that's the essence of the thing.

When you specify a header with the header() function in PHP, you're sending a response header from the server 99.9% of the time. Most of the time, you're trying to use a header to:

  • Relocate to a different page
  • Download a file

Headers can be used for a number of different things, including setting cookies, but we're not going to look at that in this article. The cookie functions in PHP can handle everything you want to do with cookies.

Relocation:

When you're relocating to a different page from PHP, the function you use looks like this:

header("Location: http://somesite.com/page.php");

Which will send that header to the browser, causing it to head over to page.php on the somesite.com domain. So, you enter it into your code, and everything works, right?

Well, not always. See, when you don't specify any headers but send output to the browser (with print(), echo(), or just standard HTML), PHP is smart enough to send it's own. (PERL, not so much, but that's a different story). So when you've output anything, including whitespace to the browser, you get message telling you Headers have already been sent.
If you're not sure why, and you haven't output anything to the browser on purpose before the headers you're sending, the first thing to do is check for whitespace right before your opening PHP tag in your code. Resolve that there is none first.

If you want a little cleaner solution, you can use ob_start() and ob_flush() to send everything into an output buffer before it gets to the browser, and have it sent all at once.
One caveat here is that you want to call ob_flush() as soon as possible, because on scripts with large output, you can slow things down considerably.

Example without output buffers:

<?PHP
if ($redirect):
header("Location: http://somesite.com/redirect.php");
exit();
endif;
?>

exit() in the above example stops the script so nothing else will be executed. Without it, you can have the unintended consequence of doing something after you meant to redirect the user to a different page.

Example with output buffering:

<?PHP

ob_start();
if ($redirect):
header("Location: http://somesite.com/redirect.php");
exit();
endif;
?>


Welcome to the site!


<?PHP
ob_flush();
?>

And that's how you can easily use header() in PHP.

Upgrading PHP from 4.3.9 to 5.2 on Cent OS4

October 6th, 2007

I recently had to migrate a client from PHP 4.3.9 to 5.2 on a godaddy virtual dedicated server running Cent OS4, and I came across a fantastic guide for doing so:

http://www.jasonlitka.com/2006/11/30/upgrading-php-520-rhel-centos/

Unfortunately, I ran into a couple of problems with that guide, including broken links to a couple of RPMS and source packages that I corrected with forum searches and from the author's other posts, which are all fantastic. That is a great site, and Jason should be commended for his commitment to helping people do what they need to on Linux Servers.

I have assembled here the steps I took to upgrade, aggregating the information I got from Jason's site as well as the filling in I had to do.
So, without further ado, here are the steps I took:

1) Log into the server as root

2) mkdir /usr/src/redhat

3) chmod 777 -R /usr/src/redhat

4) yum install wget nano make autoconf automake rpm-build postfix fileutils file libtool gcc cpp gcc-c++ perl-DBI readline-devel libc-client-devel libstdc++-devel bzip2-devel curl-devel db4-devel expat-devel gmp-devel aspell-devel httpd-devel libjpeg-devel libpng-devel pam-devel openssl-devel sqlite-devel zlib-devel pcre-devel krb5-devel cyrus-sasl-devel openldap-devel postgresql-devel unixODBC-devel libxml2-devel net-snmp-devel libxslt-devel libxml2-devel expat-devel ncurses-devel gd-devel freetype-devel

5) wget http://www.jasonlitka.com/media/files/SRPMS/php-5.2.3-jason.2.src.rpm

6) rpm -ivh php-5.2.0-8.src.rpm

7) rpm -ivh php-pear-1.4.9-4.src.rpm

8) wget http://mirrors.kernel.org/fedora/core/6/source/SRPMS/pcre-6.6-1.1.src.rpm

9) rpm -ivh pcre-6.6-1.1.src.rpm

10) cd /usr/src/redhat/SPEC

11) rpmbuild pcre.spec

12)  cd /usr/src/redhat/RPMS/i386

13) rpm -Uvh pcre*

14) cd /usr/src/redhat/SPECS

15) pmbuild -bb php.spec

16) cd /usr/src/redhat/RPMS

17) rpm -Uvh php*rpm

At this point, php installed for me fine and dandy. Next, I updated the php.ini file to reflect the new modules directory, which was /usr/lib/php4 to the 5 version, which is /usr/lib/php/modules

Then I restarted apache to reflect the changes

18) /usr/sbin/apachectl -k graceful

After that, I just checked to make sure it had installed appropriately, and that mysql was working

19) php -v (Should display 5.2.3 for the version of PHP)

You can create a php file to check for the existence of mysql_connect() as I did, or you can create a file that actually connects to your database. Either one proves out the ability to connect to MySQL from your PHP installation.

Great big hat-tip to Jason Litka of http://jasonlitka.com for his doing the heavy lifting on most of this. The only things I had a problem with when following his guide were the PCRE version (it kept asking for >= 6.6) and a broken link to the php 5.2.2 source rpm on mirrors.kernel.org, which he fixed in this post on upgrading to 5.2.3 by providing his own source package.

Hope this helps anyone stuck with an outdated PHP version who wants to use actual object-oriented code and json functions from PHP.

~A!

Welcome University of Wisonsin Students!

September 25th, 2007

Just a quick note to say hello to any students coming over from the University of Wisconsin - Eau Claire Database Management Courses.

We're happy to be able to help out in any way with your studies. If you have any questions about anything you see here, or need some help with programming or database tips and advice, please feel free to contact us at info@mypetprogrammer.com, and we'll be glad to give you a hand.

Good luck, and all the best,
~A!

Inline Values: The Ternary Operator

July 19th, 2007

So, you have a text field, and you're using an associative array to fill the values based on table data from your RDBMS, right?

You're filling the values inline, something like:

value="<?=$row['name']?>"

Which is great, so long as you're sure the row will exist. If the row doesn't, you get an E_NOTICE telling you there's an undefined index. You could turn off error reporting, and poof, it works, or you could do it right.

Turning off error reporting to mask sloppy coding practices is like stopping doctor visits once you've been diagnosed with cancer. You're still sick, you're just not hearing about it any more. And just like a disease will continue to have adverse affects whether you admit it or not, your server's error log will fill up with undefined index and undeclared variable warnings and notices. Will this cause a long term server problem? Maybe, but I doubt it.

More important, filling up the server log with garbage makes you less able to diagnose real problems and fix them, because you have to sift through millions of lines of stupid notices and warnings to get to find a "real" error.

Let's say you're pulling the row like this, and assigning the array:

$result = mysql_query("select * from users where id=1");
$user = mysql_fetch_assoc($result);

If there is no record, you have a problem. Granted, most programmers I've seen are too sloppy and lazy to care about such a problem, but the problem still exists regardless of how you feel about it.

In a situation like the above (which is not the best way to access a DB, IMHO, use classes and good architecture), you can short circuit the issue by declaring the empty array first and then using a decision block to init the data if there is something to init.

$row = array();
$result = mysql_query("select * from users where id = 1");
if (mysql_num_rows($result)):
  $row = mysql_fetch_assoc($result);
endif;

This step alone does not solve your problem, it lays the foundation by which your problem can be solved. Now, when you do an inline value (interpolated into the HTML), do it with the ternary operator:

value="<?=$row ? $row['name'] : ""?>"

The ternary operator is a standard construct in most programming languages (VB6 had IIF, but it's the same thing). The Syntax of the ternary operator is:

condition ? truepart : falsepart

Where condition is any valid statement that translates into a boolean, truepart is what to do when it's true, and falsepart is what to do when it's false.

Let's take something a teensy bit more complicated. If you have a date in the database (let's say a DateTime type), and you want to initialize to the current date if the date in the table is empty, otherwise print the date as m/d/Y, the ternary operators can be nested like so:

value="<?=$row ? $row['date'] ? date('m/d/Y', strtotime($row['date'])) : date('m/d/Y') : date('m/d/Y')?>"

Confusing? Not so much. If we use some parentheses to section it off, it looks like:

value="<?="$row ? ($row['date'] ? date('m/d/Y', strtotime($row['date'])) : date('m/d/Y') ) : date('m/d/Y')?>"

Which is the same thing as doing this (in blocks):

if ($row):
   if ($row['date']):
     print date('m/d/Y', strtotime($row['date']));
   else:
     print date('m/d/Y');
   endif;
else:
   print date('m/d/Y');
endif;

Interpolation of PHP into HTML gets a bad rap either way, because it makes code harder to maintain, and a little ugly. But if you're going to do it, and many of us still do (I don't want to have the overhead and code size of something like Smarty all the time), then do it well and correctly.

And correctly includes the use ofthe htmlspecialchars() function, but that's a topic for another day.

~A!

Mama Says $_REQUEST is the Devil

July 19th, 2007

And unlike her embarrassing mistake with the alligators, this time Mama is right.

To those unfamiliar, PHP makes available something called super global arrays that allow you to access various things, server properties ($_SERVER), cookies ($_COOKIE), post and get values ($_POST, $_GET), etc.

When you submit a page that looks like this:

http://localhost/foo.php?key=value

Your variable is available in the $_GET superglobal array. You can access it with $_GET['key']

Likewise, when you submit a form via post, you can get the form values from $_POST the same way.

$_REQUEST, however, is the grandaddy of them all, allowing you to access all of the POST, GET, and COOKIE values from one array. How convenient, right? How very courteous, to make an array I can grab anything from at any time I want. Lovely, right?

Wrong. Really wrong. Really, really, really wrong. $_REQUEST is the same thing as using register_globals to handle GET and POST. It allows anything and everything you have to be hacked given very little knowledge of your actual application internals.

For example: Let's say you have a web application with a front-end and an administration panel. You only want people with admin rights to be able to access the admin panel, most likely, so you build yourself a little login panel, and a form, which posts to a script the variables username and password. Those are then checked against the database, and boom, you're in business, knowing who to authorize and who not to.

That code would look something like this:

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query("select id from admin where username='$username' and password='$password'");

if (mysql_num_rows($result))
{
$_SESSION['admin_access'] = TRUE;
$_SESSION['admin_id'] = mysql_result($result, 0, "id");

}

(The code above is far over-simplified and only used as an example. I recommend error checking, good connection management, and database framework classes. Don't code like this.)

Now then, the problem with using $_REQUEST['username'] instead of $_POST['username'] in the example above is this: I can hack you in 2/10s of a heartbeat. Literally. Let's call this script "login_check.php" for giggles. Hitting the following URL would compromise access to your administration panel:

logincheck.php?username=foo'%20or%20true%20--

Because you're using $_REQUEST instead of the right array, username is going to be populated with the value I entered in the url, not what you thought it was going to be populated with. So, the query you thought you were executing now looks like this:

mysql_query("select id from admin where username= 'foo' or true --' ...);

And since MySQL sees everything after the two dashes as a comment, guess what? That query will ALWAYS return records, meaning that hitting it with that url will always log someone in as an administrator.

It's called SQL injection, and if you're using $_REQUEST or register_globals=On, you're asking for it to happen. Begging for it, even.

I could go on and on, but if you read this far into the piece, you care enough about your code and your professional reputation not to use $_REQUEST or register globals. And if you don't, you may never regret it, and someone will come hire me to clean up your mess later. Fine by me.

~A!

Sopranos: Road to Respect (PS2)

July 14th, 2007

I was a late comer to the whole Sopranos obsession. I have always enjoyed movies like Goodfellas, the Godfather series, Scarface, all of those. The best mob/gangland movie I've seen lately was The Departed, with Jack Nicholson, DiCaprio, and the rest.

I got my first taste of the Sopranos from a friend in Vegas when I lived there, and fell right in love with the show, albeit at the very end of the fifth season. I watched the sixth season of the Sopranos in its entirety.
So, when I heard there was a video game coming out for the PS2 entitled "The Sopranos: Road to Respect" I was psyched. So, as soon as there was a copy available over at Blockbuster Video, I snapped it up, brought it home, and started fantasizing about all the cool and nifty things they would do with a game based on an award winning HBO series.

I really should have known better. TV Series games, most movie games, they just kind of.. well... they suck. Sopranos was an exception to the rule because it sucked more. I'll explain.

In Sopranos: RTR, you play Joey LaRocca, son of the notorious rat "Big Pussy" LaRocca (the guy they shot and threw off the back of a boat a season or two ago, I never saw that episode.) In the opening scene, we see Joey smash a car window and steal an old woman's purse, and Tony Soprano knocks him over and drags him into the pork store to give him a good talking to, then offers him some work.

From there, you go on missions to do various things, one of the first of which is to dump a body in the harbor (after slamming his head into a urinal and accidentally killing him, of course.). The plot lines are egregious and over the top, but that's a mob movie/show/game all over, so that's not only acceptable, but a good thing.

The dialog interface allows you to choose three different versions of saying the same thing in a conversation. You can select "Tough", "Neutral", and "Smooth". This could have been a very cool feature, except for the fact that you have until the other person in the conversation is done speaking to choose your response type, or Neutral is automatically selected. This is prohibitively annoying, because as any RPG player knows, sometimes you need to think about your actions in a game to get the most out of them, and this game forces you to rush through the process and really detracts from the experience.

The actual game play when you're not watching cut-scenes (which are the best part of this travesty of a game) is composed mostly of punching people in various ways to intimidate them or knock them cold. There are no puzzles, your role-playing in your responses doesn't seem to affect much, and all you do is beat people up through various stages that are so linear you absolutely can not go the wrong way, ever.

And for a game entirely composed of third-person combat, the combat system sucks like a hoover with a hyperdrive. The controls are awkward, and more often than not the opponents just grab you and force you to the ground. I found the best way to win a fight with more than one opponent was to let them get me down on the ground, push the square button until I rolled them over and punch them into unconsciousness. If more than one opponent is on you at a time standing up, they just pummel you into oblivion. You're dazed after taking a hit, and the other guys beats you up, dazing you some more, then the first guy goes at it again.... and so on.

You can pick up various weapons and use the environment to your advantage, which was the only cool thing about the combat system. Everything from a filing cabinet (slamming their head in it repeatedly), to a table saw is hanging around in various stages, just waiting to be used to disable or kill your opponents.

When you're not fighting, you're wandering around looking for loot to pick up off desks, tables, magazine stands, and the like. Each piece of loot you pick up adds some money to your character's balance, but the only thing you can buy in the game is tributes for Paulie, your captain in the game. You can pay a tribute to Paulie to refill your respect meter, which appears to go down for no reason whatsoever.

The respect system. Ah, how I expected something more. I expected something a little more akin to BioWare's Knights of the Old Republic series, where you can affect your destiny and character by the choices you make in the game. Not a chance in this one, you're responses aren't really yours to choose, and they don't affect the outcome of the game unless you lose enough respect to get whacked.

I got whacked once in the game, when I shot someone at a bachelor party because I was tired of the combat system and just wanted to end the fight. Immediately, without warning, a cut scene started with my character begging not to get it in the eyes and being blown off the back of a boat by Tony and Paulie a la Big Pussy's fate. No warning, no anything except an immediate cut scene and game over.
I stuck with it, hoping against hope it would get better, and then about four hours into the game play, it was over. I had beaten the game after a long mission on the docks to kill a rival gang. Suddenly your character is a made man, the game is over, and you're left with this sinking feeling that there are still six days left to the rental, and the game has all the replay value of pong.

There were some good things, too. They used the cast from the Sopranos for the voices, and they did a great job of making the dialog you hear fun and profane as all get-out. I haven't heard the F-word that much in anything except the original series, ever. Definitely, definitely definitely not a game to have anyone under 18 in the room with you while you're playing.

With the short playing time, the absolutely horrible combat system, and the half-assed attempt at RPG elements, this game is really one of the worst I have played since Star Wars: Revenge of the Sith for the PS2.

Rent it if you must indulge your obsession with the Sopranos, but don't expect much, and definitely do not buy it.

If I was giving out stars, this game would get a 1 star rating, and even then only because the plot was fun to listen to, and I love hearing James Gandolfini talk.
~A!

Dynamic Tables: IE vs Everyone Else

June 26th, 2007

I just came off a full day fighting with a dynamic table addition, and I thought I'd go ahead and save someone else the pain.

I have a table, and I want to add rows via JavaScript when the user clicks a button. I created a function that did this. Since I develop against FireFox, I usually cross my fingers, load in IE for testing, and hope for the best.

Well, hope is, as they say, as hollow as fear.

the following function worked in FF, Opera, and Safari

JavaScript:
  1. function addRow() {
  2.   var tbl = document.getElementById('mytable');
  3.   var row = document.createElement("tr");
  4.   var td = document.createElement("td");
  5.   var input = document.createElement('input');
  6.  
  7.   td.appendChild(input);
  8.   row.appendChild(td);
  9.   tbl.appendChild(row);
  10. }

This created a new row in my table in FireFox and the like with a textfield in it. I've stripped out a lot of the extraneous properties and such, although I did add an onkeypress event to the field, twelve different fields, two select elements, and three text nodes.
Then I ran it in IE7, and nothing happened when I clicked the button. Or so it seemed. When I posted the form these were contained in, the new fields were there in the POST array, but nothing appeared on the screen.

After spending hours upon hours puzzling, googling, and trying different things, I found this:

http://msdn2.microsoft.com/en-us/library/ms532998.aspx

Which basically tells you what I am about to, but they do it in more detail. IE7 exposes a TOM (Table Object Model) that allows you to do what I wanted to very easily, except that the TOM doesn't work in any other browser. They also offer a standard DOM methodology, which is what my problem was. Here's the code that works in both IE and FireFox (untested in the others):

JavaScript:
  1. function addRow() {
  2.  
  3.   var tbl = document.getElementById('mytable');
  4.   var tbody = document.createElement('tbody');
  5.   var row = document.createElement('tr');
  6.   var td = document.createElement('td');
  7.   var input = document.createElement('input');
  8.  
  9.   td.appendChild(input);
  10.   row.appendChild(td);
  11.   // Thanks to Keith over at Etheric Arts for pointing out this line had a typo:
  12.   // tbody.appendChild(td); (Oddly enough, Firefox will add the row for you, IE will not)
  13.  
  14.   // It should be:
  15.   tbody.appendChild(tr);
  16.  
  17.   tbl.appendChild(tbody);
  18. }

Hat-tip: Keith Moulton (Link:Etheric Arts)
See, the problem here was that I was adding a tr, td, and cell contents, but no tbody element to contain them. IE 7 was enforcing standards on me that FireFox and the others overlook.

While it was a frustrating lesson, it was a powerful one. Hope it helps someone else in need.

~A!