[interchange-cvs] interchange - ton modified 2 files

interchange-core@icdevgroup.org interchange-core@icdevgroup.org
Wed Nov 6 14:48:00 2002


User:      ton
Date:      2002-11-06 19:41:48 GMT
Modified:  dist/lib/UI/pages/admin menu_editor.html
Added:     code/UI_Tag menu_load.coretag
Log:
	Revision of 'Build menu tree from database table' section
	on the menu_editor page. Inspired by and based on Mike's
	preliminary work.

	The code reponsable for the menu generation process has been
	taken out of the menu_editor page and put in a separate UI
	core tag (menu_load.coretag).
	This new setup allows for building menu's from various tables
	and table fields such as:

	1. Multiple levels of sub categories are supported by the
	   Comb_category Field feature (Level 1:Level2:...:Level n).
	2. Menu's based on Two Level Categories can be build from
	   top-level and sub-level fields in a table.
	3. Support for the area and cat tables.

	All the names of tables and fields are settable by the user
	and use proper defaults.

Revision  Changes    Path
1.1                  interchange/code/UI_Tag/menu_load.coretag


rev 1.1, prev_rev 1.0
Index: menu_load.coretag
===================================================================
UserTag menu-load Order type
UserTag menu-load addAttr
UserTag menu-load Routine <<EOR

sub old_link {
  my ($row, $nrow) = @_;
#Debug("row link_type='$row->{link_type}'");
  if($row->{link_type} eq 'external') {
	  my $first;
	  $first = $row->{url};
	  $first =~ s/\s+$//;
	  $first =~ s/^\s+//;
	  $nrow->{page} = $first;
  }
  elsif	($row->{link_type} eq 'internal') {
	  my ($page, $form) = split /\s+/, $row->{url}, 2;
	  $nrow->{page} = $page;
	  $nrow->{form} = $form;
  }
  elsif	($row->{link_type} eq 'simple') {
	  my (@items) = split /\s*[\n,]\s*/, $row->{selector};
	  my @out;
	  my $fi = $row->{tab};
	  my $sp = $row->{page};
	  my $arg = '';
	  $nrow->{page} = 'search';
	  push @out, "fi=$fi" if $fi;
	  push @out, "sp=$sp" if $sp;
	  push @out, "st=db";

	  if(! @items) {
		  push @out, "ra=yes";
		  $nrow->{form} = join "&", @out;
	  }
	  else {
		push @out, "co=yes";
		for(@items) {
			my ($col, $string) = split /\s*=\s*/;
			push @out, "sf=$col";
			push @out, "se=$string";
		}
		push @out, $row->{search}
			if $row->{search} =~ /^\s*\w\w=/;

		push @out, qq{va=banner_image=$row->{banner_image}} if $row->{banner_image};
		push @out, qq{va=banner_text=$row->{banner_text}} if $row->{banner_text};
		$arg = join "&", @out;
		$nrow->{form} = $arg;
	  }
  }
  elsif	($row->{link_type} eq 'complex') {
	  $nrow->{page} = 'search';
	  $row->{search} =~ s/[\r\n+]/\n/g;
	  $row->{search} .= qq{\nva=banner_text=$row->{banner_text}} if $row->{banner_text};
	  $row->{search} .= qq{\nva=banner_image=$row->{banner_image}} if $row->{banner_image};
	  $nrow->{form} = $row->{search};
	  $nrow->{form} =~ s/[\r\n]+/&/g;
  }
  return $nrow;
}

sub {
	my ($type, $opt) = @_;
#::logDebug("Called menu_load");
	$type ||= $opt->{type} || 'tree';

	my @menufields;
	if($opt->{menu_fields}) {
		@menufields = grep /\S/, split /[\s,\0]+/, $opt->{menu_fields};
	}
	else {
		@menufields = qw/
			code mgroup msort next_line indicator exclude_on depends_on page
			form name super inactive description help_name img_dn img_up
			img_sel img_icon url member
		/;
	}

	my %menuinit = (
				code => 0,
				inactive => 0,
				msort => "'x'",
				);

	my @out;

	if ($type eq 'tree') {
		$opt->{table} ||= 'products';
		$opt->{first_field} ||= 'prod_group';
		$opt->{second_field} ||= 'category';
		$opt->{desc_field} ||= $opt->{description_field} || 'description';
#::logDebug("menu_load options=" . uneval($opt));
		PRODBUILD: {
			my $tab = $opt->{table};
			my $db = database_exists_ref($tab)
				or do {
					Vend::Tags->error({ set => errmsg(
										"Failed to open %s table %s.",
										'products',
										$tab,
										),
									});
					last PRODBUILD;
				};
			my $tname = $db->name();
#::logDebug("LARGE=" . $db->config('LARGE'));
			$opt->{key_field} ||= $db->config('KEY');
			if(! $opt->{build_even_large} and $db->config('LARGE')) {
				Vend::Tags->error({ set => errmsg(
										"%s database %s for tree write: %s",
										'check',
										$tab,
										'too large, must override',
									),
								});
				last PRODBUILD;
			}
			my @somefields = qw/mgroup page name description/;
			my @fields = (
							$opt->{key_field},
							$opt->{first_field},
							$opt->{second_field},
							$opt->{desc_field}
						);
			my $sfields = join ",", @fields;
			my $tfields = $opt->{sort_fields} || join ",", @fields[1..$#fields];
			my $q = qq{SELECT $sfields FROM $tname ORDER BY $tfields};
			my $ary = $db->query($q)
							or do {
								Vend::Tags->error({
										set => errmsg(
											"No results from %s table %s.",
											'products',
											$tname,
										),
									});
					last PRODBUILD;
				};
			my $prev_area = '';
			my $prev_cat = '';
			@out = join "\t", @menufields;
			my @rows;
			my $base_search = "scan/co=yes/fi=$tab";

			for(@$ary) {
				my($sku, $area, $cat, $desc) = @$_;
				for( \$sku, \$area, \$cat, \$desc) {
					$$_ =~ s/\s+$//;
				}
				if($area ne $prev_area) {
					$prev_area = $area;
					$prev_cat = '';
					my $url = join '/',
								$base_search,
								"sf=$opt->{first_field}",
								"se=$area",
								"op=eq",
								"tf=$opt->{second_field},$opt->{desc_field}",
								;
					push @rows, {
							%menuinit,
							msort => 0,
							page	=> $url,
							inactive => 0,
							name => $area,
							};
				}
				if($cat ne $prev_cat) {
					$prev_cat = $cat;
					my $url = join '/',
								$base_search,
								"sf=$opt->{first_field}",
								"se=$area",
								"op=eq",
								"sf=$opt->{second_field}",
								"se=$cat",
								"op=eq",
								"tf=$opt->{desc_field}",
								;

					push @rows, {
							%menuinit,
							msort => 1,
							page	=> $url,
							inactive => 0,
							name => $cat,
							};
				}
				push @rows, {
					%menuinit,
					msort => 2,
					name => $desc,
					inactive => 0,
					page => $sku,
				};
			}

			for(@rows) {
#::logDebug("pushing out --> " . $_->{name});
				push @out, join "\t", @{$_}{@menufields};
			}
		}
	}
	elsif ($type eq 'comb_category') {
		$opt->{table} ||= 'products';
		$opt->{comb_field} ||= 'comb_category';


		COMB_BUILD: {
				my $tab = $opt->{table};
				my $comb_field = $opt->{comb_field};
				my $db = $Db{$tab}
						or do {
								$Tag->error({ set => errmsg(
										"Failed to open %s table %s.",
										'products',
										$tab,
										),
								});
								last COMB_BUILD;
							};

#Debug("LARGE=" . $db->config('LARGE'));
				if(! $CGI->{qmenu_even_large} and $db->config('LARGE')) {
					$Tag->error({ set => errmsg(
									"%s database %s for tree write: %s",
									'check',
									$tab,
									'too large, must override',
									),
					});
					last COMB_BUILD;
				}
				my @somefields = qw/mgroup page name description/;
				my $q = qq{
						SELECT $comb_field
						FROM $tab
						ORDER BY $comb_field
						};
				my $ary = $db->query($q)
							or do {
								$Tag->error({
										set => errmsg(
												"No results from %s table %s.",
												'products',
												$tab,
											),
									});
									last COMB_BUILD;
								};
				@out = join "\t", @menufields;
				my @rows;
				my @base_search = (	"bs=1", 
							"em=1", 
							"su=1", 
							"fi=$tab", 
							"st=db"
							);	
				my @levels;
				my %seen;

				$seen{$_->[0]}++ for @$ary;
				for(sort keys %seen) {
					my $comb_category = $_;
					$comb_category =~ s/\s+$//;

					my @parts = split /:/, $comb_category;
					my $combname = '';
					for( my $i = 0; $i < @parts; $i++) {
						my $level = $levels[$i] ||= {};
						my $name = $parts[$i];
						my $comb = join ":", @parts[0 .. $i];
						if(! $level->{$name}) {
							$level->{$name}++;

							my $searchterm = "se="; 
							$searchterm .= $Tag->filter('urlencode',$comb);
							my $form = join "&",
										@base_search,
										"tf=$comb_field,description",
										"sf=$comb_field",
										$searchterm
										;
							push @rows, 	{
										%menuinit,
										msort	=> $i,
										page	=> 'search',
										inactive	=> 0,
										name	=> $name,
										form	=> $form,
									};
						}
					}
				}


			for(@rows) {
#Debug("pushing out --> " . $_->{name});
				push @out, join "\t", @{$_}{@menufields};
			}
#return join("<br>",@out);
		}
	}
	elsif ($type eq 'cat_menu') {
		AREABUILD: {
			my $tab = $opt->{table} || 'area';
			my $ctab = $opt->{cat_table} || 'cat';
			my $db = database_exists_ref($tab)
				or do {
					Vend::Tags->error({ set => errmsg(
										"Failed to open %s table %s.",
										'area',
										$tab,
										),
									});
					last AREABUILD;
				};
#Debug("LARGE=" . $db->config('LARGE'));
			my $q = qq{ SELECT * FROM $tab ORDER BY sort };
			my $ary = $db->query({ sql => $q, hashref => 1 } )
							or do {
								Vend::Tags->error({
										set => errmsg(
											"No results from %s table %s.",
											'area',
											$tab,
										),
									});
							last AREABUILD;
						};

			@out = join "\t", @menufields;

			my @rows;
			my $nc = '0000';
			my $cdb = database_exists_ref($ctab)
						or do {
							Vend::Tags->error({
									set => errmsg(
										"No results from %s table %s.",
										'category',
										$tab,
									),
								});
							last AREABUILD;
						};
			my $ctabname = $cdb->name();
			foreach my $row (@$ary) {
				my $code = $row->{code};
				my $nrow = {
					code => $nc++,
					name => $row->{name},
					img_icon => $row->{image},
					msort => 0,
					mgroup => $row->{set_selector},
				};
				old_link($row, $nrow);
				my $sq = qq{
						SELECT * FROM $ctabname
						WHERE sel = '$code'
						OR    sel like '$code %'
						OR    sel like '% $code'
						OR    sel like '% $code %'
						ORDER BY sort
						};
#Debug("subquery=$sq");
				push @rows, $nrow;
				my $sary = $cdb->query({ sql => $sq, hashref => 1 });
#Debug("subquery returned: " . uneval($sary));
				for my $crow (@$sary) {
				  my $nsub = {
					  code => $nc++,
					  name => $crow->{name},
					  img_icon => $crow->{image},
					  msort => 1,
					  mgroup => $crow->{sel},
				  };
				  old_link($crow, $nsub);
				  push @rows, $nsub;
				}
			}
			for(@rows) {
#Debug("pushing out --> " . $_->{name});
				push @out, join "\t", @{$_}{@menufields};
#Debug("pushing out --> row=" . uneval($_));
			}
#Debug("qmenu_data=$Scratch->{qmenu_data}");
		}
	}
	elsif($type eq 'html') {

		my $text = $opt->{html};
		my $start = '0001';
		@out = join "\t", @menufields;
		while($text =~ s{<a(\s+.*?)</a>}{}is) {
			my $blob = $1;
			my $desc = '';
			$blob =~ m{^[^>]*\s+title=(['"]?)(.*?)\1}
				and $desc = $2;
			$blob =~ s{^.*?\shref\s*=\s*(["'])?(.*?)\1}{}is
				or next;
			my $link = $2;
			$blob =~ s/.*?>//;
			1 while $blob =~ s{<.*?>}{};
			my $anchor = $blob;
			my $sort = $start;
			$sort =~ s/./x/;
			my($href, $parms) = split /\?/, $link, 2;
			my %record = (
				code => $start++,
				msort => $sort,
				page => $href,
				form => $parms,
				name => $anchor,
				description => $desc,
			);

			push @out, join "\t", @record{@menufields};
		}

	}
	return '' unless @out;
	return join "\n", @out, '';
}
EOR




2.17      +172 -257  interchange/dist/lib/UI/pages/admin/menu_editor.html


rev 2.17, prev_rev 2.16
Index: menu_editor.html
===================================================================
RCS file: /var/cvs/interchange/dist/lib/UI/pages/admin/menu_editor.html,v
retrieving revision 2.16
retrieving revision 2.17
diff -u -r2.16 -r2.17
--- menu_editor.html	3 Oct 2002 17:53:20 -0000	2.16
+++ menu_editor.html	6 Nov 2002 19:41:48 -0000	2.17
@@ -13,6 +13,26 @@
 [set help_name]layout.edit[/set]
 [set icon_name]icon_pages.gif[/set]
 [seti ui_body_extra][/seti]
+[tmp meta_header]
+        [include include/table_populator]
+        <SCRIPT LANGUAGE=JavaScript>
+	  function toggle_comb (toggle) {
+                var el_comb = document.getElementById('combfield');
+                var el_nocomb = document.getElementById('nocombfield');
+                if(el_comb == undefined || el_nocomb == undefined)
+                        return; 
+		if (toggle == true) {
+			el_comb.style.visibility = "Visible";			
+			el_nocomb.style.visibility = "Hidden";			
+		}
+		else {
+			el_comb.style.visibility = "Hidden";			
+			el_nocomb.style.visibility = "Visible";			
+		}
+		return;
+	  }
+        </SCRIPT>
+[/tmp]
 
 @_UI_STD_HEAD_@
 <!-- ----- BEGIN REAL STUFF ----- -->
@@ -47,6 +67,55 @@
 				msort => "'x'",
 				);
 
+	if ($CGI->{qmenu_products} && $CGI->{qmenu_use_comb_field}) {
+		# Build menu from a comb_category field ('Level 1:Level 2:Level 3...Level n')
+
+		$CGI->{qmenu_comb_field} ||= 'comb_category';
+		
+		my %opt = (
+			table => $CGI->{qmenu_products},
+			comb_field => $CGI->{qmenu_comb_field},
+			type => 'comb_category',
+		);
+
+		$CGI->{qmenu_text} = $Tag->menu_load(\%opt);
+		$CGI->{qmenu_name} = '';
+		$CGI->{qmenu_new} = 'Untitled';
+	}
+	elsif ($CGI->{qmenu_products}) {
+		# Build menu from prod_group and category fields
+
+		$CGI->{qmenu_toplevel_field} ||= 'prod_group';
+		$CGI->{qmenu_sublevel_field} ||= 'category';
+
+		my %opt = (
+			table => $CGI->{qmenu_products},
+			first_field => $CGI->{qmenu_toplevel_field},
+			second_field => $CGI->{qmenu_sublevel_field},
+			type => 'tree',
+		);
+
+		$CGI->{qmenu_text} = $Tag->menu_load(\%opt);
+		$CGI->{qmenu_name} = '';
+		$CGI->{qmenu_new} = 'Untitled';
+	}
+	elsif ($CGI->{qmenu_cat}) {
+		# Build menu from top&sub level tables
+
+		$CGI->{qmenu_toplevel} ||= 'area';
+		$CGI->{qmenu_sublevel} ||= 'cat';
+		my %opt = (
+			table => $CGI->{qmenu_toplevel},
+			cat_table => $CGI->{qmenu_sublevel},
+			type => 'cat_menu',
+		);
+
+		$CGI->{qmenu_text} = $Tag->menu_load(\%opt);
+		$CGI->{qmenu_name} = '';
+		$CGI->{qmenu_new} = 'Untitled';
+
+	}
+
 	if($CGI->{qmenu_text}) {
 		my $menufile;
 		my $menuname;
@@ -171,251 +240,6 @@
 						});
 		}
 	}
-	elsif ($CGI->{qmenu_products}) {
-		PRODBUILD: {
-			my $tab = $CGI->{qmenu_products};
-			my $db = $Db{$tab}
-				or do {
-					$Tag->error({ set => errmsg(
-										"Failed to open %s table %s.",
-										'products',
-										$tab,
-										),
-									});
-					last PRODBUILD;
-				};
-#Debug("LARGE=" . $db->config('LARGE'));
-			if(! $CGI->{qmenu_even_large} and $db->config('LARGE')) {
-				$Tag->error({ set => errmsg(
-										"%s database %s for tree write: %s",
-										'check',
-										$tab,
-										'too large, must override',
-									),
-								});
-				last PRODBUILD;
-			}
-			my @somefields = qw/mgroup page name description/;
-			my $q = qq{
-						SELECT sku,prod_group,category,description
-						FROM $tab
-						ORDER BY prod_group,category,description
-						};
-			my $ary = $db->query($q)
-							or do {
-								$Tag->error({
-										set => errmsg(
-											"No results from %s table %s.",
-											'products',
-											$tab,
-										),
-									});
-					last PRODBUILD;
-				};
-			my $prev_area = '';
-			my $prev_cat = '';
-			my @out = join "\t", @menufields;
-			my @rows;
-			my $base_search = "scan/co=yes/fi=$tab";
-				
-
-			for(@$ary) {
-				my($sku, $area, $cat, $desc) = @$_;
-				for( \$sku, \$area, \$cat, \$desc) {
-					$$_ =~ s/\s+$//;
-				}
-				if($area ne $prev_area) {
-					$prev_area = $area;
-					$prev_cat = '';
-					my $url = join '/',
-								$base_search,
-								"sf=prod_group",
-								"se=$area",
-								"op=eq",
-								"tf=category,description",
-								;
-					push @rows, {
-							%menuinit,
-							msort => 0,
-							page	=> $url,
-							inactive => 0,
-							name => $area,
-							};
-				}
-				if($cat ne $prev_cat) {
-					$prev_cat = $cat;
-					my $url = join '/',
-								$base_search,
-								"sf=prod_group",
-								"se=$area",
-								"op=eq",
-								"sf=category",
-								"se=$cat",
-								"op=eq",
-								"tf=description",
-								;
-
-					push @rows, {
-							%menuinit,
-							msort => 1,
-							page	=> $url,
-							inactive => 0,
-							name => $cat,
-							};
-				}
-				push @rows, {
-					%menuinit,
-					msort => 2,
-					name => $desc,
-					inactive => 0,
-					page => $sku,
-				};
-			}
-
-			for(@rows) {
-#Debug("pushing out --> " . $_->{name});
-				push @out, join "\t", @{$_}{@menufields};
-			}
-			$Scratch->{qmenu_data} = join "\n", @out, '';
-			$CGI->{qmenu_name} = '';
-			$CGI->{qmenu_new} ||= 'Untitled';
-#Debug("qmenu_data=$Scratch->{qmenu_data}");
-		}
-	}
-	elsif ($CGI->{qmenu_cat}) {
-		AREABUILD: {
-			my $tab = $CGI->{qmenu_area} || 'area';
-			my $ctab = $CGI->{qmenu_cat} || 'cat';
-			my $db = $Db{$tab}
-				or do {
-					$Tag->error({ set => errmsg(
-										"Failed to open %s table %s.",
-										'area',
-										$tab,
-										),
-									});
-					last AREABUILD;
-				};
-#Debug("LARGE=" . $db->config('LARGE'));
-			my $q = qq{ SELECT * FROM $tab ORDER BY sort };
-			my $ary = $db->query({ sql => $q, hashref => 1 } )
-							or do {
-								$Tag->error({
-										set => errmsg(
-											"No results from %s table %s.",
-											'area',
-											$tab,
-										),
-									});
-					last AREABUILD;
-				};
-
-sub old_link {
-  my ($row, $nrow) = @_;
-#Debug("row link_type='$row->{link_type}'");
-  if($row->{link_type} eq 'external') {
-	  $first = $row->{url};
-	  $first =~ s/\s+$//;
-	  $first =~ s/^\s+//;
-	  $nrow->{page} = $first;
-  }
-  elsif	($row->{link_type} eq 'internal') {
-	  my ($page, $form) = split /\s+/, $row->{url}, 2;
-	  $nrow->{page} = $page;
-	  $nrow->{form} = $form;
-  }
-  elsif	($row->{link_type} eq 'simple') {
-	  my (@items) = split /\s*[\n,]\s*/, $row->{selector};
-	  my @out;
-	  my $fi = $row->{tab};
-	  my $sp = $row->{page};
-	  my $arg = '';
-	  $nrow->{page} = 'search';
-	  push @out, "fi=$fi" if $fi;
-	  push @out, "sp=$sp" if $sp;
-	  push @out, "st=db";
-
-	  if(! @items) {
-		  push @out, "ra=yes";
-		  $nrow->{form} = join "\n", @out;
-	  }
-	  else {
-		push @out, "co=yes";
-		for(@items) {
-			my ($col, $string) = split /\s*=\s*/;
-			push @out, "sf=$col";
-			push @out, "se=$string";
-		}
-		push @out, $row->{search}
-			if $row->{search} =~ /^\s*\w\w=/;
-
-		push @out, qq{va=banner_image=$row->{banner_image}};
-		push @out, qq{va=banner_text=$row->{banner_text}};
-		$arg = join "\n", @out;
-		$nrow->{form} = $arg;
-	  }
-  }
-  elsif	($row->{link_type} eq 'complex') {
-	  $row->{search} =~ s/[\r\n+]/\n/g;
-	  $row->{search} .= qq{\nva=banner_text=$row->{banner_text}};
-	  $row->{search} .= qq{\nva=banner_image=$row->{banner_image}};
-	  $nrow->{form} = $row->{search};
-  }
-  else {
-	  $url = "";
-  }
-  return $nrow;
-}
-
-			my @rows;
-			my $nc = '0000';
-			my $cdb = $Db{$ctab};
-			foreach my $row (@$ary) {
-				my $code = $row->{code};
-				my $nrow = {
-					code => $nc++,
-					name => $row->{name},
-					img_icon => $row->{image},
-					msort => 0,
-					mgroup => $row->{set_selector},
-				};
-				old_link($row, $nrow);
-				my $sq = qq{
-						SELECT * FROM $ctab
-						WHERE sel = '$code'
-						OR    sel like '$code %'
-						OR    sel like '% $code'
-						OR    sel like '% $code %'
-						ORDER BY sort
-						};
-#Debug("subquery=$sq");
-				push @rows, $nrow;
-				my $sary = $cdb->query({ sql => $sq, hashref => 1 });
-#Debug("subquery returned: " . uneval($sary));
-				for my $crow (@$sary) {
-				  my $nsub = {
-					  code => $nc++,
-					  name => $crow->{name},
-					  img_icon => $crow->{image},
-					  msort => 1,
-					  mgroup => $crow->{sel},
-				  };
-				  old_link($crow, $nsub);
-				  push @rows, $nsub;
-				}
-			}
-			for(@rows) {
-#Debug("pushing out --> " . $_->{name});
-				push @out, join "\t", @{$_}{@menufields};
-#Debug("pushing out --> row=" . uneval($_));
-			}
-			push @out, join
-			$Scratch->{qmenu_data} = join "\n", @out, '';
-			$CGI->{qmenu_name} = '';
-			$CGI->{qmenu_new} ||= 'Untitled';
-#Debug("qmenu_data=$Scratch->{qmenu_data}");
-		}
-	}
 
 	if($CGI->{qmenu_html_create} and $CGI->{qmenu_create}) {
 		my $text = $CGI->{qmenu_html_create};
@@ -572,17 +396,107 @@
 	[error all=1 text="<ul class=cerror><li>%s</ul>" joiner="<li>"]
 	</td>
 	<td width="30%">
-		<form action="[process href=@@MV_PAGE@@]">
-		<input type=hidden name=mv_session_id value="[data session id]">
-		<input type=hidden name=mv_action value="back">
-		Build menu tree from database table:<br>
-		<select name=qmenu_products>
-		[loop list="__ProductFiles_0__ [list-databases]" option=qmenu_products cgi=1]
-		<option> [loop-code][/loop]
-		</select> <input type=submit value=Go>
-		<br><br>
-		<input type=checkbox name="qmenu_even_large" value=1> Override, build even if large
-		</form>
+
+Build menu tree from database table(s):<br>
+[tabbed-display panel-width=300 panel-height=100
+		panel_style="
+			font-family: sans-serif;
+			font-size: 10px;
+			border: 2px;
+			border-color:#999999;
+			border-style:outset;" 
+
+				tab-width=150 
+				tab-height=20
+				panel_id=mvspan2
+				tab_style="
+    font-size:10px;
+    text-align:center;
+    font-family: sans-serif;
+    line-height:150%;
+    border:2px;
+    border-color:#999999;
+    border-style:outset;
+    border-bottom-style:none;"]
+[tabbed-panel Comb_category field]
+                <form action="[process href=@@MV_PAGE@@]" style="margin-bottom:0px;">
+                <input type=hidden name=mv_session_id value="[data session id]">
+                <input type=hidden name=mv_action value="back">
+
+[if !value qmenu_products]
+        [value name=qmenu_products set=products hide=1]
+        [value name=qmenu_comb_field set=comb_category hide=1]
+        [value name=qmenu_toplevel_field set=prod_group hide=1]
+        [value name=qmenu_sublevel_field set=category hide=1]
+[/if]
+		<select name="qmenu_products"
+        		onChange="
+                		populateTable(
+            				this.form.qmenu_products.options,
+            				this.form.qmenu_comb_field.options,
+            				this.form.qmenu_products.options[this.form.qmenu_products.selectedIndex].value
+            				);
+                		populateTable(
+            				this.form.qmenu_products.options,
+            				this.form.qmenu_toplevel_field.options,
+            				this.form.qmenu_products.options[this.form.qmenu_products.selectedIndex].value
+            				);
+                		populateTable(
+            				this.form.qmenu_products.options,
+            				this.form.qmenu_sublevel_field.options,
+            				this.form.qmenu_products.options[this.form.qmenu_products.selectedIndex].value
+            				);
+        			"
+		size=1 style="width:130px;">
+			[loop list="[list-databases]" option=qmenu_products]
+			<OPTION VALUE="[loop-code]">[loop-code]</OPTION>
+			[/loop]
+		</select> <input type=submit value=Go><br>
+<div id=combfield style="visibility:Visible;">
+		<select name="qmenu_comb_field" style="width:130px;">
+			<option value=""> -- none --
+			[loop list="[db-columns table='[value qmenu_products]']" option=qmenu_comb_field]
+			<option>[loop-code]
+			[/loop]
+		</select> Comb_Field containing category info (Default: comb_category)
+</div>
+<div id=nocombfield style="visibility:Hidden;">
+		<select name="qmenu_toplevel_field" style="width:130px;">
+			<option value=""> -- none --
+			[loop list="[db-columns table='[value qmenu_products]']" option=qmenu_toplevel_field]
+			<option>[loop-code]
+			[/loop]
+		</select> Top Level Field<br>
+		<select name="qmenu_sublevel_field" style="width:130px;">
+			<option value=""> -- none --
+			[loop list="[db-columns table='[value qmenu_products]']" option=qmenu_sublevel_field]
+			<option>[loop-code]
+			[/loop]
+		</select> Sub Level Field
+</div>
+                <input type=checkbox name="qmenu_use_comb_field" value=1 CHECKED onClick="toggle_comb(this.form.qmenu_use_comb_field.checked);"> Use comb_field&nbsp;&nbsp;
+                <input type=checkbox name="qmenu_even_large" value=1> Override, build even if large &nbsp;
+                </form>
+[/tabbed-panel]
+[tabbed-panel Top&Sub Level Tables]
+                <form action="[process href=@@MV_PAGE@@]" style="margin-bottom:0px;">
+                <input type=hidden name=mv_session_id value="[data session id]">
+                <input type=hidden name=mv_action value="back">
+                <input type=hidden name=qmenu_cat value=1>
+
+                <select name=qmenu_toplevel>
+                [loop list="area [list-databases]" option=qmenu_toplevel cgi=1]
+                <option> [loop-code][/loop]
+                </select> Top Level table (Default: area)<br>
+                <select name=qmenu_sublevel>
+                [loop list="cat [list-databases]" option=qmenu_sublevel cgi=1]
+                <option> [loop-code][/loop]
+                </select> Sub Level table (Default: cat)<br>
+                <input type=checkbox name="qmenu_even_large" value=1> Override, build even if large &nbsp;
+                <input type=submit value=Go>
+                </form>
+[/tabbed-panel]
+[/tabbed-display]
 	</td>
 </tr>
 </table>
@@ -1748,10 +1662,10 @@
 				onClick="set_mode('toggle')"
 				name=treebutton
 				value="Set tree mode">
+		<div id=treebox>
 		<input type=checkbox
 				name=show_info
 				value=1> Show item info in flyout
-		<div id=treebox>
 		<input type=checkbox name=qmenu_tree value=1> Tree mode
 		<input type=checkbox name=qmenu_write_tree value=1> Write tree to DB
 		<input type=checkbox name=showlevel value=1 onClick="toggleShowlevel()" CHECKED=1> Show numerical level
@@ -2028,3 +1942,4 @@
 </form>
 <!-- ----- END REAL STUFF ----- -->
 @_UI_STD_FOOTER_@
+