Home / Web Building Tutorials / Creating Dynamic Pull Down Menus |
|
I wrote a tutorial not too long ago on how to dynamically change select menus. I learned a lot in the weeks following the release of the tutorial to the public! I provided the basic idea, and everyone, of course, has their own vision of what they'd like that idea to be able to do. It was cool! And, several people actually sent me suggestions on how to make it better! So, I have decided to rewrite the tutorial, taking all modifications into consideration. If you have any questions, feel free to contact me at mreinfeldt@illuminetss7.com. To see an example of this script, click here. The first problem I ran into with the old version, was that it wasn't very compatible with different browsers. That's because I am new to this Jscript stuff, and forgot to test it in different ones! I was just happy to get it to work! So, I added a workaround to the original idea... basically a browser check that added one line of code if it was Netscape... But who wants to add that? So, a better way has been found. As far as I know, this new version is NS 3x, 4x, and IE4x compliant. The whole idea revolves around a stringSplit() function shown to me by Roland Hentschel. We'll begin with two select boxes and work from there, okay? You put the contents of both boxes into a single array, and then split the elements of the array apart with the splitString function. This may seem a bit redundant, but it is a good way of organizing everything. So, let's take a look at how this works... First you declare your array... var info = new Array( "Robert Jordan*The Wheel of Time|The Great Hunt", "R.A. Salvatore*The Crystal Shard| Streams of Silver|Homeland|Exile|Sojourn", "Raymond E. Feist*Magician: Apprentice| Magician: Master|Silverthorn|A Darkness At Sethanon", "David Eddings*Pawn of Prophesy|Queen of Sorcery| Magician's Gambit|Castle of Wizardry|Enchanters' End Game" ); As you can see, I'm using two different delimiters here, an asterisk * and a pipe | . This is deliberate. The * denotes the end of the first select menu's data. Everything else gets put into the second menu. The next step is the stringSplit() function. It is what we use to parse the array into useful information. It looks like this: function stringSplit ( string, delimiter ) { if ( string == null || string == "" ) { return null; } else if ( string.split != null ) { return string.split ( delimiter ); } else { var ar = new Array(); var i = 0; var start = 0; while( start >= 0 && start < string.length ) { var end = string.indexOf( delimiter, start ) ; if( end >= 0 ) { ar[i++] = string.substring( start, end ); start = end+1; } else { ar[i++] = string.substring( start, string.length ); start = -1; } } return ar; } } If this function makes no sense to you, don't worry... it works! That's what's important, right? Okay, first of all, I did not write this function. I do not know who did. (If you know who did, email me, and I will give that person their due credit!) It is nice, though. I have read that JavaScript 1.2 has a built-in split() function, so this one may become obsolete in the near future. However, until then, this one does work on older browsers (which jscript 1.2 may not). StringSplit needs to be passed two parameters; the string it is supposed to split, and the delimiting character. Obviously, you need to save the results somewhere, right? So, before we go any further, let's create two new arrays; menu1 and menu2. var menu1 = new Array(); Okay, now that we have our two arrays we can begin our next function, the createMenus() function. This function actually does two things. It splits up our *info" array, and then loads the data into the select boxes. Let's take a look at it, and then I'll explain what each part does. function createMenus () { for ( var i=0; i < info.length; i++ ) { menu1[i] = stringSplit ( info[i], '*' ); menu2[i] = stringSplit ( menu1[i][1], '|' ); } var author = document.myForm.main; var book = document.myForm.title; author.length = menu1.length; book.length = menu2[0].length; for ( var i=0; i < menu1.length; i++ ) { author.options[i].value = menu1[i][0]; author.options[i].text = menu1[i][0]; } document.myForm.main.selected = 0; for (var x=0; x < menu2[0].length; x++) { book.options[x].text = menu2[0][x]; book.options[x].value = menu2[0][x]; } document.myForm.title.selected = 0; } The part highlighted in red is where we'll begin. The for-loop goes through each element of our info array. We take that element, info[i] and split it into two parts using an asterisk as our delimiter. That result is stored in the array element menu1[i]. Now we take that result and split it apart! Actually, what we're doing is separating the string that follows the asterisk. Confused? Me too! Let's lay it out. When we did the first split, our menu1[i] had the following data put into it: menu[i][0] = Robert Jordan In other words, we have created a two dimensional array. So, our second splitString() call, splits up the item stored in menu[i][1] into a new, one-dimensional array that will look like this: menu2[0] = The Wheel of Time See how neatly that works? That gives us the information we need in two arrays, which we can then loop through to create our menus. That's what the next part is all about. We start by creating aliases for our menus (otherwise it's too much to type each time!). var author = document.myForm.main; The next step is to set the length of each of those menus. If you don't do this step, you will get errors! What we do, is set the length of the menu to the length of its corresponding array, like this: author.length = menu1.length; Now that we've done that, we can load the menus with data. The loops themselves are very self-explanatory, so I'm not going to belabor them. Please notice that it is possible to set the default 'selected' value for each select menu. I default them to zero, but there may be instances when you would want to choose another number. Okay, now the only thing we need to do is create the function that will make these menus dynamic! Let's take a look at the code, and then walk through it. function updateMenus ( what ) { var sel = what.selectedIndex; if ( sel >= 0 && sel < menu1.length ) var temp = menu2[sel]; else var temp = new Array (); what.form.title.length = temp.length; for ( var i = 0; i < temp.length; i++ ) { what.form.title.options[i].text = temp[i]; what.form.title.options[i].value = temp[i]; } what.form.title.selected=0; } The first thing to know here is that we will be passing in the this value. If you haven't dealt with it before, it's a very handy little variable. I'd suggest looking it up on Netscape's Javascript Reference site or some other site that gives good definitions and examples. So, to begin with, we find out which item in the 'main' menu was selected, and give it a variable of its own. Then we check to make sure that it falls within our boundaries. If it doesn't, that is to say, if it is greater than the number of entries we have or less than zero, we create a new, empty array. This may seem like overkill, but it does keep you from crashing if something does happen. Next, we reset the length of the 'title' menu to the length of the array we will be filling it with. Then we loop through, just as we did in the createMenus() function, and fill the menu. That's it! Well, almost. We still have to create our form and menus so that this code has somewhere put its information! So, in the < body > statement add the following: < body onLoad="createMenus()"> That will make sure that the menus get loaded when the page is called up. Then create your form and select statements. What is important here is that the names you use match the names you used in the functions up above. Obviously, the names I've created can be substituted with your own. Now, one other note. I've found, that to make this look nice on Netscape, we have to do a little formatting of our < option > statements. If you don't do this, it will look really ugly on Netscape! So, without further ado! < form name="myForm" > Author's name: < select name="main" size=1 onChange="updateMenus(this)"> < option > < option > < option > < /select > < p > Titles: < select name="title" size=1 > < option > < option > < option > < /select > < /form > Two things to note here. Firstly, the onChange in the 'main' menu. That tells the browser to call the jscript function when you make a selection in the first menu. Secondly, after the first option statement of each select statement, you have to enter a series of non-breaking spaces. If you don't know how to do that, look at the source code for this page, and find this section. After the first option you will see a series of codes. That's what it has to look like. That's it, folks! We're done! You can play with this, and make it do some pretty neat things. I will be putting together a little "how-to" on how to use this for a list of links (which is a little more complicated!). To see an example of that, take a look at the source code for my home page. Hope you learned something! If you do have any comments or questions, feel free to contact me. This tutorial is written and contributed by Matt Reinfeldt, a surfer of JavaScript Kit, and programmer/analyst at Illuminet. Matt has a personal web site, and can be visited here. |
. http://www.javascriptkit.com |