Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Is there a way to shorten this set of controls for two select lists?

Status
Not open for further replies.

MrCBofBCinTX

Technical User
Dec 24, 2003
164
US
I am generating two select lists from perl.
One shows a class drop down list.
The second one shows a subclass drop down list.

To make life easier, this makes only subclasses that are in a class show up after selecting a class.
Works good. I just rewrote the perl subroutine that generates this to be much faster.
Good!
Now I want to see if there is a better way to write the javascript part.
What I have is very long and will only get longer as more classes and subclasses are added.
I am not a Javascript programmer (cut and paste), so any advice will be helpful.

I have another set of category and subcategory drop downs I would like to tie together like these two, but reasonable speed is necessary.

JavaScript:
<script type="text/javascript">
//<![CDATA[
if (window.addEventListener) {
	window.addEventListener("load",setupEventsC,false);
} else if (window.attachEvent) {
	window.attachEvent("onload",setupEventsC);
} else {
	window.onload=setupEventsC;
}

function setupEventsC(evnt) {
	var opts = document.getElementById("someForm").class_selected.options;
	var subclass_selected = document.getElementById("someForm").subclass_selected.options;
					subclass_selected[subclass_selected.length] = new Option("All", "All");
    subclass_selected[subclass_selected.length] = new Option("Construction", "Construction");
subclass_selected[subclass_selected.length] = new Option("Floor", "Floor");
subclass_selected[subclass_selected.length] = new Option("Misc", "Misc");
subclass_selected[subclass_selected.length] = new Option("Wallpaper", "Wallpaper");
subclass_selected[subclass_selected.length] = new Option("Wood", "Wood");
subclass_selected[subclass_selected.length] = new Option("Storage", "Storage");
subclass_selected[subclass_selected.length] = new Option("Aluminum", "Aluminum");
subclass_selected[subclass_selected.length] = new Option("Steel", "Steel");
subclass_selected[subclass_selected.length] = new Option("Wood", "Wood");
subclass_selected[subclass_selected.length] = new Option("Panels", "Panels");
subclass_selected[subclass_selected.length] = new Option("Sinks", "Sinks");
subclass_selected[subclass_selected.length] = new Option("Adhesive", "Adhesive");
etc...
	document.getElementById("someForm").class_selected.onchange = checkSelectC;
	
}

function checkSelectC(evnt) {
	var opts = document.getElementById("someForm").class_selected.options;
	var subclass_selected = document.getElementById("someForm").subclass_selected.options;

	for ( var i = 0; i < opts.length; i++) {
		if ( opts[i].selected ) {
			switch(opts[i].value) {
            case 'All' :
            subclass_selected[subclass_selected.length] = new Option("Construction", "Construction");
subclass_selected[subclass_selected.length] = new Option("Floor", "Floor");
subclass_selected[subclass_selected.length] = new Option("Misc", "Misc");
subclass_selected[subclass_selected.length] = new Option("Wallpaper", "Wallpaper");
subclass_selected[subclass_selected.length] = new Option("Wood", "Wood");
subclass_selected[subclass_selected.length] = new Option("Storage", "Storage");
subclass_selected[subclass_selected.length] = new Option("Aluminum", "Aluminum");
subclass_selected[subclass_selected.length] = new Option("Steel", "Steel");
subclass_selected[subclass_selected.length] = new Option("Wood", "Wood");
subclass_selected[subclass_selected.length] = new Option("Panels", "Panels");
subclass_selected[subclass_selected.length] = new Option("Sinks", "Sinks");
subclass_selected[subclass_selected.length] = new Option("Adhesive", "Adhesive");
subclass_selected[subclass_selected.length] = new Option("Silicone", "Silicone");
subclass_selected[subclass_selected.length] = new Option("Electric", "Electric");
etc..
break;
case 'Adhesive' :
subclass_selected.length = 0;
subclass_selected[subclass_selected.length] = new Option("All", "All");
subclass_selected[subclass_selected.length] = new Option("Construction", "Construction");
subclass_selected[subclass_selected.length] = new Option("Floor", "Floor");
subclass_selected[subclass_selected.length] = new Option("Misc", "Misc");
subclass_selected[subclass_selected.length] = new Option("Wallpaper", "Wallpaper");
subclass_selected[subclass_selected.length] = new Option("Wood", "Wood");
break;
case 'Attic' :
subclass_selected.length = 0;
subclass_selected[subclass_selected.length] = new Option("All", "All");
subclass_selected[subclass_selected.length] = new Option("Storage", "Storage");
break;
etc..

			}
		}
	}

	return false;
}
</script>
 
Hi

Use a multidimensional array or an object to store all data, then iterate over the array item's value corresponding to the selected option and populate the second control.

See the similar discussions in the old thread216-1587540, thread216-1593411 and thread216-1599528.

Feherke.
[link feherke.github.com/][/url]
 
The one of the other threads was perfect advice.
I have got the first function down to a small array and it works fine.

JavaScript:
function setupEventsC(evnt) {
	var opts = document.getElementById("someForm").class_selected.options;
	var subclass_selected = document.getElementById("someForm").subclass_selected.options;
      document.getElementById("someForm").subclass_selected.options.length=1;
  for (var i=0,l=cat.length;i<l;i++)
    getElementById("someForm").subclass_selected.options[i+1]=new Option(cat[i],cat[i]);
	subclass_selected[subclass_selected.length] = new Option("All", "All");
	document.getElementById("someForm").class_selected.onchange = checkSelectC;

This creates cat variable:

Perl:
#######################################################################
#       This section successfully creates javascript variable cat
        my @all_subclasses_aref;
        my $statement = "SELECT DISTINCT (class, subclass) FROM products WHERE class IS NOT NULL;";
        $sth = $dbh->prepare($statement);
        my $rv1 = $sth->execute();
        my $classsuball;
        my @class_sub;
        my $old_class = '';
        my $class;
        my $subclass;
        #######################################################################
        #   This sections works perfect
        #   BEGIN
        $array = qq|var cat={
|;
        CASE:
        while  (@all_subclasses_aref   = $sth->fetchrow_array()) {
            $classsuball = $all_subclasses_aref[0];
            $classsuball =~ s/\(//g;
            $classsuball =~ s/\)//g;
            $classsuball =~ s/"//g;
            @class_sub = split /,/, $classsuball;
            $class = $class_sub[0];
            $subclass = $class_sub[1] || '';
            if ($class eq $old_class) {
                if ($subclass ne '') {
                    $array .= qq{, '$subclass'};
                }
                next CASE;
            } elsif ($old_class ne '') {
                $array .= qq{],
};
                $array .= qq{'$class':['All', '$subclass'};
            }
            else {
                $array .= qq{'$class':['All', '$subclass'};
            }
            $old_class = $class;
        }
        $array .= "]
        }";
        $array =~ s/, ''//g;
        #######################################################################
        #   END

I also rewrote my poor SQL to work very fast.

But I do not see how to work with the switch/case function.

JavaScript:
function checkSelectC(evnt) {
	var opts = document.getElementById("someForm").class_selected.options;
	var subclass_selected = document.getElementById("someForm").subclass_selected.options;

	for ( var i = 0; i < opts.length; i++) {
		if ( opts[i].selected ) {
			switch(opts[i].value) {
				$case_stringc
			}
		}
	}

	return false;
}

How should I go about getting
JavaScript:
switch

case 'This':
      blah blah
break;
case 'That':
     something
     someone
     somwhere
break;
etc..
out of being a long list in the page?

Thanks
 
Hi

Sorry, is abit hard to me to reproduce your JSON from the Perl code. So I show another example. Obvious parts of the code omitted to keep it as simple as possible.

If you have controls like this where you want to populate [tt]select[/tt] second based on what was selected in [tt]select[/tt] first :
HTML:
[b]<select[/b] [maroon]name[/maroon][teal]=[/teal][green][i]"first"[/i][/green][b]><option>[/b]one[b]</option><option>[/b]two[b]</option></select>[/b]
[b]<select[/b] [maroon]name[/maroon][teal]=[/teal][green][i]"second"[/i][/green][b]></select>[/b]
Then this is how you did it originally :
Code:
[b]switch[/b] [teal]([/teal]first[teal].[/teal]text[teal])[/teal] [teal]{[/teal]
  [b]case[/b] [green][i]'one'[/i][/green][teal]:[/teal]
    second[teal].[/teal]options[teal].[/teal][COLOR=darkgoldenrod]add[/color][teal]([/teal][b]new[/b] [COLOR=darkgoldenrod]Option[/color][teal]([/teal][green][i]'foo'[/i][/green][teal]))[/teal]
    second[teal].[/teal]options[teal].[/teal][COLOR=darkgoldenrod]add[/color][teal]([/teal][b]new[/b] [COLOR=darkgoldenrod]Option[/color][teal]([/teal][green][i]'bar'[/i][/green][teal]))[/teal]
  [b]break[/b]
  [b]case[/b] [green][i]'two'[/i][/green][teal]:[/teal]
    second[teal].[/teal]options[teal].[/teal][COLOR=darkgoldenrod]add[/color][teal]([/teal][b]new[/b] [COLOR=darkgoldenrod]Option[/color][teal]([/teal][green][i]'fiz'[/i][/green][teal]))[/teal]
    second[teal].[/teal]options[teal].[/teal][COLOR=darkgoldenrod]add[/color][teal]([/teal][b]new[/b] [COLOR=darkgoldenrod]Option[/color][teal]([/teal][green][i]'baz'[/i][/green][teal]))[/teal]
  [b]break[/b]
[teal]}[/teal]
And this is how I suggested to do it :
Code:
[b]var[/b] cat[teal]=[/teal][teal]{[/teal]
  one[teal]:[/teal] [teal][[/teal][green][i]'foo'[/i][/green][teal],[/teal][green][i]'bar'[/i][/green][teal]],[/teal]
  two[teal]:[/teal] [teal][[/teal][green][i]'fiz'[/i][/green][teal],[/teal][green][i]'baz'[/i][/green][teal]],[/teal]
[teal]}[/teal]

[b]for[/b] [teal]([/teal][b]var[/b] i[teal]=[/teal][purple]0[/purple][teal],[/teal]l[teal]=[/teal]cat[teal][[/teal]first[teal].[/teal]text[teal]].[/teal]length[teal];[/teal]i[teal]<[/teal]l[teal];[/teal]i[teal]++)[/teal]
  second[teal].[/teal]options[teal].[/teal][COLOR=darkgoldenrod]add[/color][teal]([/teal][b]new[/b] [COLOR=darkgoldenrod]Option[/color][teal]([/teal]cat[teal][[/teal]first[teal].[/teal]text[teal]][[/teal]i[teal]]))[/teal]

Feherke.
[link feherke.github.com/][/url]
 
I have made this work now.
But I don't like the way that the width of the subsection fields jumps after selecting the category.

I want to stabilize this width, but not allow anything but 'All' in the subsection field unless a category is selected first.

I do not want to visually pre-populate the subsections.

Should I look at this as a css problem (everything is in a table)? Or can I fix this with my Javascript code?
The maximum length in both fields changes as the database is updated.
 
two possible solutions come to mind:

1. provide a fixed width for the select box
2. populate the select box with all possible values. retrieve the active width of the select box and specify that as the width in css (via javascript), then remove the option values that are not needed.

 
1. provide a fixed width for the select box
I can't do that one, since some of the critical information shows up at the very end.
Seeing:
blahblah
blahblah
blahblah

instead of:
blahblah1
blahblah2
blahblah3

Hmm, but I might be able to do a < style="" > on the fly since I will have the actual option lengths when building the page.

2. populate the select box with all possible values. retrieve the active width of the select box and specify that as the width in css (via javascript), then remove the option values that are not needed.

That also sounds like a reasonable solution.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top